From 2205dc58734d86ac318a7b33024acd6e5bd58c4a Mon Sep 17 00:00:00 2001 From: "Vikas@easifem@archlinux@work" Date: Tue, 3 Oct 2023 11:31:06 +0900 Subject: [PATCH 001/117] Update: FiniteElement WIP: on FiniteElement data structure --- src/modules/AbstractFE/CMakeLists.txt | 22 ++ .../src/AbstractFE_Class.F90 | 21 +- src/modules/CMakeLists.txt | 9 + src/modules/FiniteElement/CMakeLists.txt | 2 - .../FiniteElement/src/FiniteElement_Class.F90 | 1 - .../FiniteElementFactory/CMakeLists.txt | 22 ++ .../src/FiniteElementFactory.F90 | 1 + src/modules/MixedFiniteElement/CMakeLists.txt | 22 ++ .../src/MixedFiniteElement_Class.F90 | 249 ++++++++++++++++++ src/submodules/AbstractFE/CMakeLists.txt | 29 ++ .../AbstractFE_Class@ConstructorMethods.F90 | 17 ++ .../src/AbstractFE_Class@DGMethods.F90 | 0 .../src/AbstractFE_Class@GetMethods.F90 | 0 .../src/AbstractFE_Class@H1Methods.F90 | 0 .../src/AbstractFE_Class@HCurlMethods.F90 | 0 .../src/AbstractFE_Class@HDivMethods.F90 | 0 .../src/AbstractFE_Class@IOMethods.F90 | 0 .../AbstractFE_Class@QuadratureMethods.F90 | 0 .../src/AbstractFE_Class@SetMethods.F90 | 0 src/submodules/CMakeLists.txt | 6 + src/submodules/FiniteElement/CMakeLists.txt | 9 - .../MixedFiniteElement/CMakeLists.txt | 21 ++ .../src/MixedFiniteElement_Class@Methods.F90 | 162 ++++++++++++ .../src/PLPlot_Class@ConstructorMethods.F90 | 13 + 24 files changed, 590 insertions(+), 16 deletions(-) create mode 100644 src/modules/AbstractFE/CMakeLists.txt rename src/modules/{FiniteElement => AbstractFE}/src/AbstractFE_Class.F90 (98%) create mode 100644 src/modules/FiniteElementFactory/CMakeLists.txt rename src/modules/{FiniteElement => FiniteElementFactory}/src/FiniteElementFactory.F90 (96%) create mode 100644 src/modules/MixedFiniteElement/CMakeLists.txt create mode 100644 src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 create mode 100644 src/submodules/AbstractFE/CMakeLists.txt rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@ConstructorMethods.F90 (98%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@DGMethods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@GetMethods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@H1Methods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@HCurlMethods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@HDivMethods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@IOMethods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@QuadratureMethods.F90 (100%) rename src/submodules/{FiniteElement => AbstractFE}/src/AbstractFE_Class@SetMethods.F90 (100%) create mode 100644 src/submodules/MixedFiniteElement/CMakeLists.txt create mode 100644 src/submodules/MixedFiniteElement/src/MixedFiniteElement_Class@Methods.F90 diff --git a/src/modules/AbstractFE/CMakeLists.txt b/src/modules/AbstractFE/CMakeLists.txt new file mode 100644 index 000000000..ef114c62f --- /dev/null +++ b/src/modules/AbstractFE/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractFE_Class.F90 +) diff --git a/src/modules/FiniteElement/src/AbstractFE_Class.F90 b/src/modules/AbstractFE/src/AbstractFE_Class.F90 similarity index 98% rename from src/modules/FiniteElement/src/AbstractFE_Class.F90 rename to src/modules/AbstractFE/src/AbstractFE_Class.F90 index 5c79aa85c..0df6d4f3a 100644 --- a/src/modules/FiniteElement/src/AbstractFE_Class.F90 +++ b/src/modules/AbstractFE/src/AbstractFE_Class.F90 @@ -36,6 +36,9 @@ MODULE AbstractFE_Class PUBLIC :: SetAbstractFEParam PUBLIC :: AbstractFEDeallocate PUBLIC :: AbstractFEDisplay +PUBLIC :: AbstractFEInitiate +PUBLIC :: AbstractFECheckEssentialParam +PUBLIC :: DEALLOCATE CHARACTER(*), PARAMETER :: modName = "AbstractFE_Class" @@ -262,8 +265,6 @@ MODULE SUBROUTINE AbstractFECheckEssentialParam(obj, param, prefix) END SUBROUTINE AbstractFECheckEssentialParam END INTERFACE -PUBLIC :: AbstractFECheckEssentialParam - !---------------------------------------------------------------------------- ! SetAbstractFEParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -372,8 +373,6 @@ MODULE SUBROUTINE AbstractFEInitiate(obj, param, prefix) END SUBROUTINE AbstractFEInitiate END INTERFACE -PUBLIC :: AbstractFEInitiate - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -403,6 +402,20 @@ MODULE SUBROUTINE fe_Deallocate(obj) END SUBROUTINE fe_Deallocate END INTERFACE AbstractFEDeallocate +!---------------------------------------------------------------------------- +! Deallocate@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Deallocate the vector of NeumannBC_ + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Ptr_Vector(obj) + TYPE(AbstractFEPointer_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Ptr_Vector +END INTERFACE DEALLOCATE + !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 8dac227be..422069b24 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -165,9 +165,18 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PolynomialFactory/CMakeLists.txt) # RefElement INCLUDE(${CMAKE_CURRENT_LIST_DIR}/RefElement/CMakeLists.txt) +# AbstractFE +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFE/CMakeLists.txt) + # FiniteElement INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FiniteElement/CMakeLists.txt) +# MixedFiniteElement +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MixedFiniteElement/CMakeLists.txt) + +# FiniteElementFactory +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FiniteElementFactory/CMakeLists.txt) + # Tree3R INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Tree3R/CMakeLists.txt) diff --git a/src/modules/FiniteElement/CMakeLists.txt b/src/modules/FiniteElement/CMakeLists.txt index 83c70956f..205dcb289 100644 --- a/src/modules/FiniteElement/CMakeLists.txt +++ b/src/modules/FiniteElement/CMakeLists.txt @@ -18,7 +18,5 @@ SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") TARGET_SOURCES( ${PROJECT_NAME} PRIVATE - ${src_path}/AbstractFE_Class.F90 ${src_path}/FiniteElement_Class.F90 - ${src_path}/FiniteElementFactory.F90 ) diff --git a/src/modules/FiniteElement/src/FiniteElement_Class.F90 b/src/modules/FiniteElement/src/FiniteElement_Class.F90 index 44f282008..84ace8b9d 100644 --- a/src/modules/FiniteElement/src/FiniteElement_Class.F90 +++ b/src/modules/FiniteElement/src/FiniteElement_Class.F90 @@ -13,7 +13,6 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see -! MODULE FiniteElement_Class USE GlobalData diff --git a/src/modules/FiniteElementFactory/CMakeLists.txt b/src/modules/FiniteElementFactory/CMakeLists.txt new file mode 100644 index 000000000..fbe06e7f4 --- /dev/null +++ b/src/modules/FiniteElementFactory/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/FiniteElementFactory.F90 +) diff --git a/src/modules/FiniteElement/src/FiniteElementFactory.F90 b/src/modules/FiniteElementFactory/src/FiniteElementFactory.F90 similarity index 96% rename from src/modules/FiniteElement/src/FiniteElementFactory.F90 rename to src/modules/FiniteElementFactory/src/FiniteElementFactory.F90 index 56852a5d3..09aa4c5d3 100644 --- a/src/modules/FiniteElement/src/FiniteElementFactory.F90 +++ b/src/modules/FiniteElementFactory/src/FiniteElementFactory.F90 @@ -18,4 +18,5 @@ MODULE FiniteElementFactory USE AbstractFE_Class USE FiniteElement_Class +USE MixedFiniteElement_Class END MODULE FiniteElementFactory diff --git a/src/modules/MixedFiniteElement/CMakeLists.txt b/src/modules/MixedFiniteElement/CMakeLists.txt new file mode 100644 index 000000000..2cebe5b0b --- /dev/null +++ b/src/modules/MixedFiniteElement/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/MixedFiniteElement_Class.F90 +) diff --git a/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 b/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 new file mode 100644 index 000000000..146e84032 --- /dev/null +++ b/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 @@ -0,0 +1,249 @@ +! 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 MixedFiniteElement_Class +USE GlobalData +USE AbstractRefElement_Class +USE AbstractFE_Class +USE FiniteElement_Class, ONLY: FiniteElementPointer_ +USE FPL, ONLY: ParameterList_ +USE Domain_Class, ONLY: Domain_, DomainPointer_ +IMPLICIT NONE +PRIVATE +PUBLIC :: MixedFiniteElement_ +PUBLIC :: MixedFiniteElementPointer_ +PUBLIC :: SetMixedFiniteElementParam +PUBLIC :: DEALLOCATE +PUBLIC :: Initiate +CHARACTER(*), PARAMETER :: modName = "MixedFiniteElement_Class" +CHARACTER(*), PARAMETER :: myprefix = "MixedFiniteElement" + +!---------------------------------------------------------------------------- +! AbstractRefElement_ +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-08-13 +! summary: Finite element class +! +!{!pages/docs-api/MixedFiniteElement/MixedFiniteElement_.md!} + +TYPE, EXTENDS(AbstractFE_) :: MixedFiniteElement_ + TYPE(FiniteElementPointer_), ALLOCATABLE :: fe(:) +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => fe_Initiate + !! Constructor method for AbstractFE element + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => fe_Deallocate + !! Deallocate data stored in Mixed finite element + !! This method can be overloaded by Subclass of this abstract class. + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & fe_CheckEssentialParam +END TYPE MixedFiniteElement_ + +!---------------------------------------------------------------------------- +! FiniteElementPointer_ +!---------------------------------------------------------------------------- + +TYPE :: MixedFiniteElementPointer_ + CLASS(MixedFiniteElement_), POINTER :: ptr => NULL() +END TYPE MixedFiniteElementPointer_ + +!---------------------------------------------------------------------------- +! CheckEssentialParam@Methods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2023-08-11 +! summary: This routine Check the essential parameters in param. + +INTERFACE + MODULE SUBROUTINE fe_CheckEssentialParam(obj, param) + CLASS(MixedFiniteElement_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE fe_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-02 +! summary: Initiates an instance of the finite element + +INTERFACE + MODULE SUBROUTINE fe_Initiate(obj, param) + CLASS(MixedFiniteElement_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE fe_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-02 +! summary: Initiates an instance of the finite element + +INTERFACE DEALLOCATE + MODULE SUBROUTINE fe_Deallocate(obj) + CLASS(MixedFiniteElement_), INTENT(INOUT) :: obj + END SUBROUTINE fe_Deallocate +END INTERFACE DEALLOCATE + +!---------------------------------------------------------------------------- +! Deallocate@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-25 +! summary: Deallocate a vector of FiniteElement + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Vector(obj) + TYPE(MixedFiniteElement_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Vector +END INTERFACE DEALLOCATE + +!---------------------------------------------------------------------------- +! Deallocate@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Deallocate the vector of NeumannBC_ + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Ptr_Vector(obj) + TYPE(MixedFiniteElementPointer_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Ptr_Vector +END INTERFACE DEALLOCATE + +!---------------------------------------------------------------------------- +! SetAbstractFEParam@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-08-11 +! summary: Sets the parameters for initiating abstract finite element + +INTERFACE + MODULE SUBROUTINE SetMixedFiniteElementParam( & + & param, & + & tFiniteElements, & + & iFiniteElement, & + & nsd, & + & elemType, & + & baseContinuity, & + & baseInterpolation, & + & ipType, & + & basisType, & + & alpha, & + & beta, & + & lambda, & + & order, & + & anisoOrder, & + & edgeOrder, & + & faceOrder, & + & cellOrder) + TYPE(ParameterList_), INTENT(INOUT) :: param + INTEGER(I4B), INTENT(IN) :: tFiniteElements + !! Total number of finite elements + INTEGER( I4B ), INTENT( IN ) :: iFiniteElement + !! Finite element number + INTEGER(I4B), INTENT(IN) :: nsd + !! Number of spatial dimension + INTEGER(I4B), INTENT(IN) :: elemType + !! Type of finite element + !! Line, Triangle, Quadrangle, Tetrahedron, Prism, Pyramid, + !! Hexahedron + CHARACTER(*), INTENT(IN) :: baseContinuity + !! Continuity or Conformity of basis function. + !! This parameter is used to determine the nodal coordinates of + !! reference element, when xij is not present. + !! If xij is present then this parameter is ignored + !! H1* (default), HDiv, HCurl, DG + CHARACTER(*), INTENT(IN) :: baseInterpolation + !! Basis function family used for interpolation. + !! This parameter is used to determine the nodal coordinates of + !! reference element, when xij is not present. + !! If xij is present then this parameter is ignored + !! LagrangeInterpolation, LagrangePolynomial + !! SerendipityInterpolation, SerendipityPolynomial + !! HierarchyInterpolation, HierarchyPolynomial + !! OrthogonalInterpolation, OrthogonalPolynomial + !! HermitInterpolation, HermitPolynomial + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ipType + !! Interpolation point type, It is required when + !! baseInterpol is LagrangePolynomial + INTEGER(I4B), OPTIONAL, INTENT(IN) :: basisType(:) + !! Basis type: Legendre, Lobatto, Ultraspherical, + !! Jacobi, Monomial + REAL(DFP), OPTIONAL, INTENT(IN) :: alpha(:) + !! Jacobi parameter + REAL(DFP), OPTIONAL, INTENT(IN) :: beta(:) + !! Jacobi parameter + REAL(DFP), OPTIONAL, INTENT(IN) :: lambda(:) + !! Ultraspherical parameters + INTEGER(I4B), OPTIONAL, INTENT(IN) :: order + !! Isotropic Order of finite element + INTEGER(I4B), OPTIONAL, INTENT(IN) :: anisoOrder(:) + !! Anisotropic order, order in x, y, and z directions + INTEGER(I4B), OPTIONAL, INTENT(IN) :: edgeOrder(:) + !! Order of approximation along edges + INTEGER(I4B), OPTIONAL, INTENT(IN) :: faceOrder(:) + !! Order of approximation along face + INTEGER(I4B), OPTIONAL, INTENT(IN) :: cellOrder(:) + !! Order of approximation along cell + END SUBROUTINE SetMixedFiniteElementParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Initiate vector of FiniteElement pointers + +INTERFACE Initiate + MODULE SUBROUTINE fe_Initiate1(obj, param, dom) + TYPE(MixedFiniteElementPointer_), ALLOCATABLE, INTENT(INOUT) :: obj(:) + TYPE(ParameterList_), INTENT(IN) :: param + CLASS(Domain_), INTENT(IN) :: dom + END SUBROUTINE fe_Initiate1 +END INTERFACE Initiate + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Initiate vector of FiniteElement pointers + +INTERFACE Initiate + MODULE SUBROUTINE fe_Initiate2(obj, param, dom) + TYPE(MixedFiniteElementPointer_), ALLOCATABLE, INTENT(INOUT) :: obj(:) + TYPE(ParameterList_), INTENT(IN) :: param + CLASS(DomainPointer_), INTENT(IN) :: dom(:) + END SUBROUTINE fe_Initiate2 +END INTERFACE Initiate + +END MODULE MixedFiniteElement_Class diff --git a/src/submodules/AbstractFE/CMakeLists.txt b/src/submodules/AbstractFE/CMakeLists.txt new file mode 100644 index 000000000..948c8c85a --- /dev/null +++ b/src/submodules/AbstractFE/CMakeLists.txt @@ -0,0 +1,29 @@ +# 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}/AbstractFE_Class@ConstructorMethods.F90 + ${src_path}/AbstractFE_Class@IOMethods.F90 + ${src_path}/AbstractFE_Class@GetMethods.F90 + ${src_path}/AbstractFE_Class@SetMethods.F90 + ${src_path}/AbstractFE_Class@H1Methods.F90 + ${src_path}/AbstractFE_Class@HDivMethods.F90 + ${src_path}/AbstractFE_Class@HCurlMethods.F90 + ${src_path}/AbstractFE_Class@DGMethods.F90 + ${src_path}/AbstractFE_Class@QuadratureMethods.F90 +) diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@ConstructorMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@ConstructorMethods.F90 similarity index 98% rename from src/submodules/FiniteElement/src/AbstractFE_Class@ConstructorMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@ConstructorMethods.F90 index 71f25edb9..6b38a50d0 100644 --- a/src/submodules/FiniteElement/src/AbstractFE_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractFE/src/AbstractFE_Class@ConstructorMethods.F90 @@ -970,6 +970,23 @@ END SUBROUTINE SetFEPram_Heirarchy3D obj%isInitiated = .FALSE. END PROCEDURE fe_Deallocate +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Deallocate_Ptr_Vector +INTEGER(I4B) :: ii +IF (ALLOCATED(obj)) THEN + DO ii = 1, SIZE(obj) + IF (ASSOCIATED(obj(ii)%ptr)) THEN + CALL obj(ii)%ptr%DEALLOCATE() + obj(ii)%ptr => NULL() + END IF + END DO + DEALLOCATE (obj) +END IF +END PROCEDURE Deallocate_Ptr_Vector + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@DGMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@DGMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@DGMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@DGMethods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@GetMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@GetMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@GetMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@GetMethods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@H1Methods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@H1Methods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@H1Methods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@H1Methods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@HCurlMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@HCurlMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@HCurlMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@HCurlMethods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@HDivMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@HDivMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@HDivMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@HDivMethods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@IOMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@IOMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@IOMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@IOMethods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@QuadratureMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@QuadratureMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@QuadratureMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@QuadratureMethods.F90 diff --git a/src/submodules/FiniteElement/src/AbstractFE_Class@SetMethods.F90 b/src/submodules/AbstractFE/src/AbstractFE_Class@SetMethods.F90 similarity index 100% rename from src/submodules/FiniteElement/src/AbstractFE_Class@SetMethods.F90 rename to src/submodules/AbstractFE/src/AbstractFE_Class@SetMethods.F90 diff --git a/src/submodules/CMakeLists.txt b/src/submodules/CMakeLists.txt index fd9a37c97..d279480d4 100644 --- a/src/submodules/CMakeLists.txt +++ b/src/submodules/CMakeLists.txt @@ -237,9 +237,15 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/UserFunction/CMakeLists.txt) # RefElement INCLUDE(${CMAKE_CURRENT_LIST_DIR}/RefElement/CMakeLists.txt) +# AbstractFE +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFE/CMakeLists.txt) + # FiniteElement INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FiniteElement/CMakeLists.txt) +# MixedFiniteElement +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MixedFiniteElement/CMakeLists.txt) + # AbstractPlot INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractPlot/CMakeLists.txt) diff --git a/src/submodules/FiniteElement/CMakeLists.txt b/src/submodules/FiniteElement/CMakeLists.txt index 5eadeed80..50a807093 100644 --- a/src/submodules/FiniteElement/CMakeLists.txt +++ b/src/submodules/FiniteElement/CMakeLists.txt @@ -17,14 +17,5 @@ SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") TARGET_SOURCES( ${PROJECT_NAME} PRIVATE - ${src_path}/AbstractFE_Class@ConstructorMethods.F90 - ${src_path}/AbstractFE_Class@IOMethods.F90 - ${src_path}/AbstractFE_Class@GetMethods.F90 - ${src_path}/AbstractFE_Class@SetMethods.F90 - ${src_path}/AbstractFE_Class@H1Methods.F90 - ${src_path}/AbstractFE_Class@HDivMethods.F90 - ${src_path}/AbstractFE_Class@HCurlMethods.F90 - ${src_path}/AbstractFE_Class@DGMethods.F90 - ${src_path}/AbstractFE_Class@QuadratureMethods.F90 ${src_path}/FiniteElement_Class@Methods.F90 ) diff --git a/src/submodules/MixedFiniteElement/CMakeLists.txt b/src/submodules/MixedFiniteElement/CMakeLists.txt new file mode 100644 index 000000000..e53199778 --- /dev/null +++ b/src/submodules/MixedFiniteElement/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}/MixedFiniteElement_Class@Methods.F90 +) diff --git a/src/submodules/MixedFiniteElement/src/MixedFiniteElement_Class@Methods.F90 b/src/submodules/MixedFiniteElement/src/MixedFiniteElement_Class@Methods.F90 new file mode 100644 index 000000000..93c26e919 --- /dev/null +++ b/src/submodules/MixedFiniteElement/src/MixedFiniteElement_Class@Methods.F90 @@ -0,0 +1,162 @@ +! 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(MixedFiniteElement_Class) Methods +USE ExceptionHandler_Class, ONLY: e +USE FiniteElement_Class, ONLY: Deallocate_FE => DEALLOCATE +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_Initiate +CHARACTER(*), PARAMETER :: myName = "fe_Initiate()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP] :: The method is under development.') +! CALL AbstractFEInitiate(obj=obj, param=param, prefix=myprefix) +END PROCEDURE fe_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_Deallocate +CHARACTER(*), PARAMETER :: myName = "fe_Deallocate()" +CALL Deallocate_FE(obj) +CALL DEALLOCATE (obj%fe) +END PROCEDURE fe_Deallocate + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "fe_CheckEssentialParam()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP] :: The method is under development') +! CALL AbstractFECheckEssentialParam(obj=obj, param=param, prefix=myprefix) +END PROCEDURE fe_CheckEssentialParam + +!---------------------------------------------------------------------------- +! SetFiniteElementParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetMixedFiniteElementParam +CHARACTER(*), PARAMETER :: myName = "SetMixedFiniteElementParam()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP] :: The method is under development.') +! CALL SetAbstractFEParam( & +! & param=param, & +! & prefix=myprefix, & +! & nsd=nsd, & +! & elemType=elemType, & +! & baseContinuity=baseContinuity, & +! & baseInterpolation=baseInterpolation, & +! & ipType=ipType, & +! & basisType=basisType, & +! & alpha=alpha, & +! & beta=beta, & +! & lambda=lambda, & +! & order=order, & +! & anisoOrder=anisoOrder, & +! & edgeOrder=edgeOrder, & +! & faceOrder=faceOrder, & +! & cellOrder=cellOrder) +END PROCEDURE SetMixedFiniteElementParam + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Deallocate_Vector +INTEGER(I4B) :: ii +IF (ALLOCATED(obj)) THEN + DO ii = 1, SIZE(obj) + CALL obj(ii)%DEALLOCATE() + END DO + DEALLOCATE (obj) +END IF +END PROCEDURE Deallocate_Vector + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Deallocate_Ptr_Vector +INTEGER(I4B) :: ii +IF (ALLOCATED(obj)) THEN + DO ii = 1, SIZE(obj) + IF (ASSOCIATED(obj(ii)%ptr)) THEN + CALL obj(ii)%ptr%DEALLOCATE() + obj(ii)%ptr => NULL() + END IF + END DO + DEALLOCATE (obj) +END IF +END PROCEDURE Deallocate_Ptr_Vector + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_Initiate1 +CHARACTER(*), PARAMETER :: myName = "fe_Initiate1()" + +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP] :: This method is under development.') + +! TYPE(ParameterList_), POINTER :: sublist +! INTEGER(I4B) :: ierr, ii, tElemType +! INTEGER(I4B), ALLOCATABLE :: elemType(:) +! +! sublist => NULL() +! +! IF (.NOT. param%isSubList(key=myPrefix)) THEN +! CALL e%RaiseError(modName//'::'//myName//' - '// & +! & '[ARGUMENT ERROR] :: '//myprefix//' should be a sublist') +! END IF +! +! ierr = param%GetSubList(key=myprefix, sublist=sublist) +! +! elemType = dom%GetElemType(dim=-1_I4B) +! tElemType = SIZE(elemType) +! +! CALL DEALLOCATE (obj) +! ALLOCATE(obj(tElemType) ) +! +! DO ii = 1, SIZE(elemType) +! ierr = sublist%Set(key=myprefix//"/elemType", VALUE=elemType(ii)) +! ALLOCATE(FiniteElement_::obj(ii)%ptr) +! CALL obj(ii)%ptr%Initiate(param=param) +! END DO +! +! sublist => NULL() +! IF (ALLOCATED(elemType)) DEALLOCATE (elemType) +END PROCEDURE fe_Initiate1 + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_Initiate2 +CHARACTER(*), PARAMETER :: myName = "fe_Initiate2()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP] :: This method is under development.') +END PROCEDURE fe_Initiate2 + +END SUBMODULE Methods diff --git a/src/submodules/PLPlot/src/PLPlot_Class@ConstructorMethods.F90 b/src/submodules/PLPlot/src/PLPlot_Class@ConstructorMethods.F90 index 52ace17ff..f60fa4a85 100644 --- a/src/submodules/PLPlot/src/PLPlot_Class@ConstructorMethods.F90 +++ b/src/submodules/PLPlot/src/PLPlot_Class@ConstructorMethods.F90 @@ -51,6 +51,18 @@ MODULE PROCEDURE GetDeviceName TYPE(String) :: extn extn = getExtension(filename) +#ifdef Darwin_SYSTEM + +SELECT CASE (TRIM(LowerCase(extn%chars()))) +CASE ("pdf"); ans = "pdfcairo" +CASE ("png"); ans = "pngcairo" +CASE ("ps"); ans = "ps" +CASE ("eps"); ans = "epscairo" +CASE ("svg"); ans = "svg" +CASE ("jpeg", "jpg"); ans = "pngcairo" +END SELECT +#else + SELECT CASE (TRIM(LowerCase(extn%chars()))) CASE ("pdf"); ans = "pdf" CASE ("png"); ans = "pngqt" @@ -59,6 +71,7 @@ CASE ("svg"); ans = "svg" CASE ("jpeg", "jpg"); ans = "jpgqt" END SELECT +#endif END PROCEDURE GetDeviceName END SUBMODULE ConstructorMethods From de25dfbc605c667beac12c07076448a39754ba7d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 3 Oct 2023 17:46:07 +0900 Subject: [PATCH 002/117] Update: AbstractNodeField_Class Updating: Updating structure of AbstractNodeField WIP: Trying new data structure for finite elements and field variables --- .../AbstractField/src/AbstractField_Class.F90 | 169 ++++++++++++++++-- .../src/AbstractNodeField_Class.F90 | 112 +++--------- .../src/AbstractField_Class@Methods.F90 | 79 +++++++- .../src/AbstractNodeField_Class@Methods.F90 | 165 +++++++---------- 4 files changed, 313 insertions(+), 212 deletions(-) diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index c4126a01f..0da8ea0e8 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -48,6 +48,11 @@ MODULE AbstractField_Class INTEGER(I4B), PARAMETER, PUBLIC :: FIELD_TYPE_CONSTANT_TIME = 4 CHARACTER(*), PARAMETER :: modName = "AbstractField_Class" PUBLIC :: AbstractFieldInitiate +PUBLIC :: AbstractFieldDisplay +PUBLIC :: AbstractFieldImport +PUBLIC :: AbstractFieldExport +PUBLIC :: AbstractFieldDeallocate +PUBLIC :: FIELD_TYPE_NUMBER !---------------------------------------------------------------------------- ! AbstractField_ @@ -124,6 +129,15 @@ MODULE AbstractField_Class GENERIC, PUBLIC :: WriteData => WriteData_vtk, WriteData_hdf5 PROCEDURE, PASS(obj), NON_OVERRIDABLE, PUBLIC :: GetParam PROCEDURE, PASS(obj), NON_OVERRIDABLE, PUBLIC :: SetParam + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalPhysicalVars & + & => aField_GetTotalPhysicalVars + !! Returns the total number of physical variables + !! INFO: This routine should be implemented by child classes + !! For block matrices the physical variables are more than one, + !! for example, presesure and velocity. + PROCEDURE, PUBLIC, PASS(obj) :: GetPhysicalNames => aField_GetPhysicalNames + !! Returns the names of physical variables + !! INFO: This routine should be implemented by child classes PROCEDURE, PUBLIC, PASS(obj) :: GetSpaceCompo => aField_GetSpaceCompo !! Return space component !! INFO: This routine should be implemented by child classes @@ -133,9 +147,26 @@ MODULE AbstractField_Class PROCEDURE, PUBLIC, PASS(obj) :: GetStorageFMT => aField_GetStorageFMT !! Return storage format !! INFO: This routine should be implemented by child classes + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalDOF => aField_GetTotalDOF + !! Returns the total number of degree of freedoms + !! This is same as calling Size + !! INFO: This routine should be implemented by child classes + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalVertexDOF => aField_GetTotalVertexDOF + !! Returns the total number of vertex degree of freedoms + !! INFO: This routine should be implemented by child classes + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalEdgeDOF => aField_GetTotalEdgeDOF + !! Returns the total number of edge degree of freedoms + !! INFO: This routine should be implemented by child classes + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalFaceDOF => aField_GetTotalFaceDOF + !! Returns the total number of face degree of freedoms + !! INFO: This routine should be implemented by child classes + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalCellDOF => aField_GetTotalCellDOF + !! Returns the total number of cell degree of freedoms + !! INFO: This routine should be implemented by child classes PROCEDURE, PUBLIC, PASS(obj), NON_OVERRIDABLE :: isConstant & - & => aField_isConstant + & => aField_isConstant !! It returns true if the field is constant field + !! INFO: This routine should be implemented by child classes END TYPE AbstractField_ PUBLIC :: AbstractField_ @@ -248,8 +279,6 @@ END SUBROUTINE aField_Display MODULE PROCEDURE aField_Display END INTERFACE AbstractFieldDisplay -PUBLIC :: AbstractFieldDisplay - !---------------------------------------------------------------------------- ! IMPORT !---------------------------------------------------------------------------- @@ -268,8 +297,6 @@ END SUBROUTINE aField_Import MODULE PROCEDURE aField_Import END INTERFACE AbstractFieldImport -PUBLIC :: AbstractFieldImport - !---------------------------------------------------------------------------- ! Export !---------------------------------------------------------------------------- @@ -286,8 +313,6 @@ END SUBROUTINE aField_Export MODULE PROCEDURE aField_Export END INTERFACE AbstractFieldExport -PUBLIC :: AbstractFieldExport - !---------------------------------------------------------------------------- ! Export !---------------------------------------------------------------------------- @@ -302,8 +327,6 @@ END SUBROUTINE aField_Deallocate MODULE PROCEDURE aField_Deallocate END INTERFACE AbstractFieldDeallocate -PUBLIC :: AbstractFieldDeallocate - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -315,8 +338,6 @@ MODULE PURE FUNCTION FIELD_TYPE_NUMBER(name) RESULT(Ans) END FUNCTION FIELD_TYPE_NUMBER END INTERFACE -PUBLIC :: FIELD_TYPE_NUMBER - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -446,6 +467,36 @@ MODULE SUBROUTINE GetParam(obj, & END SUBROUTINE GetParam END INTERFACE +!---------------------------------------------------------------------------- +! GetTotalPhysicalVars +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-03 +! summary: Returns the total number of physical variables + +INTERFACE + MODULE FUNCTION aField_GetTotalPhysicalVars(obj) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION aField_GetTotalPhysicalVars +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPhysicalNames +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the names of physical variables + +INTERFACE + MODULE SUBROUTINE aField_GetPhysicalNames(obj, ans) + CLASS(AbstractField_), INTENT(IN) :: obj + CHARACTER(*) :: ans(:) + END SUBROUTINE aField_GetPhysicalNames +END INTERFACE + !---------------------------------------------------------------------------- ! GetSpaceCompo !---------------------------------------------------------------------------- @@ -455,9 +506,12 @@ END SUBROUTINE GetParam ! summary: Returns space components INTERFACE - MODULE FUNCTION aField_GetSpaceCompo(obj) RESULT(ans) + MODULE FUNCTION aField_GetSpaceCompo(obj, tPhysicalVars) RESULT(ans) CLASS(AbstractField_), INTENT(IN) :: obj - INTEGER(I4B), ALLOCATABLE :: ans(:) + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + !! Total number of physical variables + !! This can be obtained from GetTotalPhysicalVars method + INTEGER(I4B) :: ans(tPhysicalVars) END FUNCTION aField_GetSpaceCompo END INTERFACE @@ -470,9 +524,10 @@ END FUNCTION aField_GetSpaceCompo ! summary: Returns Time components INTERFACE - MODULE FUNCTION aField_GetTimeCompo(obj) RESULT(ans) + MODULE FUNCTION aField_GetTimeCompo(obj, tPhysicalVars) RESULT(ans) CLASS(AbstractField_), INTENT(IN) :: obj - INTEGER(I4B), ALLOCATABLE :: ans(:) + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) END FUNCTION aField_GetTimeCompo END INTERFACE @@ -491,6 +546,89 @@ MODULE FUNCTION aField_GetStorageFMT(obj) RESULT(ans) END FUNCTION aField_GetStorageFMT END INTERFACE +!---------------------------------------------------------------------------- +! GetTotalDOF +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the total number of degree of freedoms +! +!# Introduction +! This method is same as calling the size function. + +INTERFACE + MODULE FUNCTION aField_GetTotalDOF(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION aField_GetTotalDOF +END INTERFACE + +!---------------------------------------------------------------------------- +! GetTotalVertexDOF +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the total number of vertex degree of freedoms + +INTERFACE + MODULE FUNCTION aField_GetTotalVertexDOF(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION aField_GetTotalVertexDOF +END INTERFACE + +!---------------------------------------------------------------------------- +! GetTotalEdgeDOF +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the total number of Edge degree of freedoms + +INTERFACE + MODULE FUNCTION aField_GetTotalEdgeDOF(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION aField_GetTotalEdgeDOF +END INTERFACE + +!---------------------------------------------------------------------------- +! GetTotalFaceDOF +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the total number of Face degree of freedoms + +INTERFACE + MODULE FUNCTION aField_GetTotalFaceDOF(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION aField_GetTotalFaceDOF +END INTERFACE + +!---------------------------------------------------------------------------- +! GetTotalCellDOF +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the total number of Cell degree of freedoms + +INTERFACE + MODULE FUNCTION aField_GetTotalCellDOF(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION aField_GetTotalCellDOF +END INTERFACE + !---------------------------------------------------------------------------- ! isConstant !---------------------------------------------------------------------------- @@ -504,4 +642,5 @@ MODULE FUNCTION aField_isConstant(obj) RESULT(ans) LOGICAL(LGT) :: ans END FUNCTION aField_isConstant END INTERFACE + END MODULE AbstractField_Class diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index c042ed111..648223bc4 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -22,7 +22,6 @@ MODULE AbstractNodeField_Class USE Domain_Class, ONLY: DomainPointer_, Domain_ USE HDF5File_Class, ONLY: HDF5File_ USE VTKFile_Class, ONLY: VTKFile_ -USE FiniteElement_Class, ONLY: FiniteElementPointer_ IMPLICIT NONE PRIVATE PUBLIC :: AbstractNodeFieldDisplay @@ -48,15 +47,33 @@ MODULE AbstractNodeField_Class ! summary: Abstract node field TYPE, ABSTRACT, EXTENDS(AbstractField_) :: AbstractNodeField_ + INTEGER(I4B) :: dof_tPhysicalVars = 0_I4B + !! Total number of physical variables + !! NOTE: This variable is only for internal use + INTEGER(I4B) :: dof_storageFMT = NODES_FMT + !! Storage format + !! NOTE: This variable is only for internal use + INTEGER(I4B), ALLOCATABLE :: dof_spaceCompo(:) + !! Spatial components + !! NOTE: This variable is only for internal use + INTEGER(I4B), ALLOCATABLE :: dof_timeCompo(:) + !! NOTE: This variable is only for internal use + INTEGER(I4B), ALLOCATABLE :: dof_tNodes(:) + !! Total number of nodes + !! NOTE: This variable is only for internal use + CHARACTER(1), ALLOCATABLE :: dof_names_char(:) + !! Single character name of physical variable + !! NOTE: This variable is only for internal use INTEGER(I4B) :: tSize = 0 !! Total length of the nodal field = tdof * tNodes + !! NOTE: This variable is only for internal use TYPE(RealVector_) :: realVec !! Vector of reals to contains the nodes + !! NOTE: This variable is only for internal use TYPE(DOF_) :: dof !! Degree of freedom object, which contains the information about !! how the different components are stored inside the realVec - TYPE(FiniteElementPointer_), ALLOCATABLE :: fe(:) - !! Finite element + !! NOTE: This variable is only for internal use CONTAINS PROCEDURE, PUBLIC, PASS(obj) :: Display => anf_Display !! Display the content of AbstractNodeField @@ -81,17 +98,6 @@ MODULE AbstractNodeField_Class !! Set single entry PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => anf_GetSingle !! Get single entry - PROCEDURE, PUBLIC, PASS(obj) :: GetTotalDOF => anf_GetTotalDOF - !! Returns the total number of degree of freedoms - !! This is same as calling Size - PROCEDURE, PUBLIC, PASS(obj) :: GetTotalVertexDOF => anf_GetTotalVertexDOF - !! Returns the total number of vertex degree of freedoms - PROCEDURE, PUBLIC, PASS(obj) :: GetTotalEdgeDOF => anf_GetTotalEdgeDOF - !! Returns the total number of edge degree of freedoms - PROCEDURE, PUBLIC, PASS(obj) :: GetTotalFaceDOF => anf_GetTotalFaceDOF - !! Returns the total number of face degree of freedoms - PROCEDURE, PUBLIC, PASS(obj) :: GetTotalCellDOF => anf_GetTotalCellDOF - !! Returns the total number of cell degree of freedoms END TYPE AbstractNodeField_ !---------------------------------------------------------------------------- @@ -333,84 +339,6 @@ MODULE FUNCTION anf_Size(obj, dims) RESULT(ans) END FUNCTION anf_Size END INTERFACE -!---------------------------------------------------------------------------- -! GetTotalDOF -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Returns the total number of degree of freedoms -! -!# Introduction -! This method is same as calling the size function. - -INTERFACE - MODULE FUNCTION anf_GetTotalDOF(obj) RESULT(ans) - CLASS(AbstractNodeField_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION anf_GetTotalDOF -END INTERFACE - -!---------------------------------------------------------------------------- -! GetTotalVertexDOF -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Returns the total number of vertex degree of freedoms - -INTERFACE - MODULE FUNCTION anf_GetTotalVertexDOF(obj) RESULT(ans) - CLASS(AbstractNodeField_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION anf_GetTotalVertexDOF -END INTERFACE - -!---------------------------------------------------------------------------- -! GetTotalEdgeDOF -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Returns the total number of Edge degree of freedoms - -INTERFACE - MODULE FUNCTION anf_GetTotalEdgeDOF(obj) RESULT(ans) - CLASS(AbstractNodeField_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION anf_GetTotalEdgeDOF -END INTERFACE - -!---------------------------------------------------------------------------- -! GetTotalFaceDOF -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Returns the total number of Face degree of freedoms - -INTERFACE - MODULE FUNCTION anf_GetTotalFaceDOF(obj) RESULT(ans) - CLASS(AbstractNodeField_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION anf_GetTotalFaceDOF -END INTERFACE - -!---------------------------------------------------------------------------- -! GetTotalCellDOF -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Returns the total number of Cell degree of freedoms - -INTERFACE - MODULE FUNCTION anf_GetTotalCellDOF(obj) RESULT(ans) - CLASS(AbstractNodeField_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION anf_GetTotalCellDOF -END INTERFACE - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 index d6e700e8f..18873ef1e 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 @@ -534,12 +534,34 @@ END PROCEDURE aField_Import +!---------------------------------------------------------------------------- +! GetTotalPhysicalVars +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalPhysicalVars + CHARACTER(*), PARAMETER :: myName="aField_GetTotalPhysicalVars()" + CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& + & 'child classes') +END PROCEDURE aField_GetTotalPhysicalVars + +!---------------------------------------------------------------------------- +! aField_GetPhysicalNames +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetPhysicalNames +CHARACTER(*), PARAMETER :: myName = "aField_GetNames()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & + & " child classes.") +END PROCEDURE aField_GetPhysicalNames + !---------------------------------------------------------------------------- ! GetSpaceCompo !---------------------------------------------------------------------------- MODULE PROCEDURE aField_GetSpaceCompo -CHARACTER(*), PARAMETER :: myName = "aField_GetSpaceCompo" +CHARACTER(*), PARAMETER :: myName = "aField_GetSpaceCompo()" CALL e%RaiseError(modName//'::'//myName//' - '// & & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & & " child classes.") @@ -567,6 +589,61 @@ & " child classes.") END PROCEDURE aField_GetStorageFMT +!---------------------------------------------------------------------------- +! GetTotalDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalDOF()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' // & + & ' child classes') +END PROCEDURE aField_GetTotalDOF + +!---------------------------------------------------------------------------- +! GetTotalVertexDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalVertexDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalVertexDOF()" +CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& + & 'child classes') +END PROCEDURE aField_GetTotalVertexDOF + +!---------------------------------------------------------------------------- +! GetTotalEdgeDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalEdgeDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalEdgeDOF()" +CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& + & 'child classes') +END PROCEDURE aField_GetTotalEdgeDOF + +!---------------------------------------------------------------------------- +! GetTotalFaceDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalFaceDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalFaceDOF()" +CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& + & 'child classes') +END PROCEDURE aField_GetTotalFaceDOF + +!---------------------------------------------------------------------------- +! GetTotalCellDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalCellDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalCellDOF()" +CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& + & 'child classes') +END PROCEDURE aField_GetTotalCellDOF + !---------------------------------------------------------------------------- ! isConstant !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 index 16784b8be..11dd53ec2 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 @@ -18,13 +18,11 @@ USE BaseMethod USE ExceptionHandler_Class, ONLY: e USE HDF5File_Method -USE FiniteElement_Class, ONLY: Deallocate_FE => DEALLOCATE, & -& Initiate_FE => Initiate IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! Display +! Display !---------------------------------------------------------------------------- MODULE PROCEDURE anf_Display @@ -42,72 +40,17 @@ END PROCEDURE anf_GetPointer !---------------------------------------------------------------------------- -! Size +! Size !---------------------------------------------------------------------------- MODULE PROCEDURE anf_size CHARACTER(*), PARAMETER :: myName = "anf_size" CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This method is under development') + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') ! ans = obj%tSize END PROCEDURE anf_size -!---------------------------------------------------------------------------- -! GetTotalDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_GetTotalDOF -CHARACTER(*), PARAMETER :: myName = "anf_GetTotalDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This method is under development') -! IF (ASSOCIATED(obj%domain)) THEN -! ! ans = GetTotalDOF(obj=fem, dom=obj%domain) -! END IF -! -! IF (ALLOCATED(obj%domains)) THEN -! END IF -END PROCEDURE anf_GetTotalDOF - -!---------------------------------------------------------------------------- -! GetTotalVertexDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_GetTotalVertexDOF -CHARACTER(*), PARAMETER :: myName = "anf_GetTotalVertexDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This method is under development') -END PROCEDURE anf_GetTotalVertexDOF - -!---------------------------------------------------------------------------- -! GetTotalEdgeDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_GetTotalEdgeDOF -CHARACTER(*), PARAMETER :: myName = "anf_GetTotalEdgeDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This method is under development') -END PROCEDURE anf_GetTotalEdgeDOF - -!---------------------------------------------------------------------------- -! GetTotalFaceDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_GetTotalFaceDOF -CHARACTER(*), PARAMETER :: myName = "anf_GetTotalFaceDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This method is under development') -END PROCEDURE anf_GetTotalFaceDOF - -!---------------------------------------------------------------------------- -! GetTotalCellDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_GetTotalCellDOF -CHARACTER(*), PARAMETER :: myName = "anf_GetTotalCellDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This method is under development') -END PROCEDURE anf_GetTotalCellDOF - !---------------------------------------------------------------------------- ! Initiate2 !---------------------------------------------------------------------------- @@ -128,7 +71,6 @@ obj%tSize = obj2%tSize obj%realVec = obj2%realVec obj%dof = obj2%dof - ! CALL obj%fe%Copy(obj2%fe) END SELECT END PROCEDURE anf_initiate2 @@ -153,10 +95,12 @@ obj%tSize = 0 CALL DEALLOCATE (obj%realVec) CALL DEALLOCATE (obj%dof) -IF (ALLOCATED(obj%fe)) THEN - CALL DEALLOCATE_FE(obj%fe) - ! NOTE: This module is called from FiniteElement_Class -END IF +obj%dof_tPhysicalVars = 0 +obj%dof_storageFMT = NODES_FMT +IF (ALLOCATED(obj%dof_spaceCompo)) DEALLOCATE (obj%dof_spaceCompo) +IF (ALLOCATED(obj%dof_timeCompo)) DEALLOCATE (obj%dof_timeCompo) +IF (ALLOCATED(obj%dof_tNodes)) DEALLOCATE (obj%dof_tNodes) +IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) END PROCEDURE anf_Deallocate !---------------------------------------------------------------------------- @@ -247,7 +191,7 @@ ! info CALL e%raiseInformation(modName//"::"//myName//" - "// & -& "[END] Export()") + & "[END] Export()") END PROCEDURE anf_Export @@ -295,47 +239,60 @@ MODULE PROCEDURE AbstractNodeFieldInitiate CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate" -INTEGER(I4B), ALLOCATABLE :: spaceCompo(:) -INTEGER(I4B), ALLOCATABLE :: timeCompo(:) -INTEGER(I4B) :: storageFMT -CHARACTER(1), ALLOCATABLE :: names_char(:) CALL e%RaiseError(modName//'::'//myName//' - '// & & '[WIP] :: This routine is under development') -! CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) -! CALL Initiate_FE(obj=obj%fe, param=param, dom=dom) -! !INFO: Initiate_FE is defined in FiniteElement_Class -! spaceCompo = obj%GetSpaceCompo() -! timeCompo = obj%GetTimeCompo() -! storageFMT = obj%GetStorageFMT() -! ! names_char = obj%GetNames() -! !FIXME: How to get the names in the vase of block matrix? -! -! IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN -! tNodes = 1 -! ELSE -! tNodes = obj%GetTotalDOF() -! END IF -! -! CALL Initiate( & -! & obj=obj%dof, & -! & tNodes=tNodes, & -! & names=names_char, & -! & spaceCompo=spaceCompo, & -! & timeCompo=timeCompo, & -! & storageFMT=storageFMT) -! -! CALL Initiate(obj%realVec, obj%dof) -! -! obj%tSize = SIZE(obj%realVec) -! -! IF (obj%local_n .EQ. 0) THEN -! obj%local_n = obj%tSize -! END IF -! IF (obj%global_n .EQ. 0) THEN -! obj%global_n = obj%tSize -! END IF +CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) + +IF (obj%dof_tPhysicalVars .EQ. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INITIATE ERROR] :: AbstractNodeField_::obj%dof_tPhysicalVars is 0') +END IF + +IF (.NOT. ALLOCATED(obj%dof_spaceCompo)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INITIATE ERROR] :: AbstractNodeField_::obj%dof_spaceCompo '// & + & ' is NOT ALLOCATED') +END IF + +IF (.NOT. ALLOCATED(obj%dof_timeCompo)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INITIATE ERROR] :: AbstractNodeField_::obj%dof_timeCompo '// & + & ' is NOT ALLOCATED') +END IF + +IF (.NOT. ALLOCATED(obj%dof_tNodes)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INITIATE ERROR] :: AbstractNodeField_::obj%dof_tNodes '// & + & ' is NOT ALLOCATED') +END IF + +IF (.NOT. ALLOCATED(obj%dof_names_char)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INITIATE ERROR] :: AbstractNodeField_::obj%dof_names_char '// & + & ' is NOT ALLOCATED') +END IF + +CALL Initiate( & + & obj=obj%dof, & + & tNodes=obj%dof_tNodes, & + & names=obj%dof_names_char, & + & spaceCompo=obj%dof_spaceCompo, & + & timeCompo=obj%dof_timeCompo, & + & storageFMT=obj%dof_storageFMT) + +CALL Initiate(obj=obj%realVec, dofobj=obj%dof) + +obj%tSize = SIZE(obj%realVec) + +IF (obj%local_n .EQ. 0) THEN + obj%local_n = obj%tSize +END IF + +IF (obj%global_n .EQ. 0) THEN + obj%global_n = obj%tSize +END IF END PROCEDURE AbstractNodeFieldInitiate From d20f378216ec8e225559c36e658bdda93378d1a3 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 3 Oct 2023 17:48:00 +0900 Subject: [PATCH 003/117] Update: ScalarField_Class Formatting: Minor formatting in ScalarField_Class --- .../ScalarField/src/ScalarField_Class.F90 | 206 +++++++++--------- 1 file changed, 107 insertions(+), 99 deletions(-) diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index 38e6586c1..935b55726 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -59,55 +59,59 @@ MODULE ScalarField_Class & sField_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => sField_Initiate1 FINAL :: sField_Final - PROCEDURE, PASS(obj) :: set1 => sField_set1 - !! set single entry - PROCEDURE, PASS(obj) :: set2 => sField_set2 - !! set all values to a scalar values - PROCEDURE, PASS(obj) :: set3 => sField_set3 - !! set all values to a given vector - PROCEDURE, PASS(obj) :: set4 => sField_set4 - !! set selected values to given scalar - PROCEDURE, PASS(obj) :: set5 => sField_set5 - !! set selected values to given vector - PROCEDURE, PASS(obj) :: set6 => sField_set6 - !! set values to a scalar by using triplet - PROCEDURE, PASS(obj) :: set7 => sField_set7 - !! set values to a vector by using triplet - PROCEDURE, PASS(obj) :: set8 => sField_set8 + PROCEDURE, PASS(obj) :: Set1 => sField_set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => sField_set2 + !! Set all values to a scalar values + PROCEDURE, PASS(obj) :: Set3 => sField_set3 + !! Set all values to a given vector + PROCEDURE, PASS(obj) :: Set4 => sField_set4 + !! Set selected values to given scalar + PROCEDURE, PASS(obj) :: Set5 => sField_set5 + !! Set selected values to given vector + PROCEDURE, PASS(obj) :: Set6 => sField_set6 + !! Set values to a scalar by using triplet + PROCEDURE, PASS(obj) :: Set7 => sField_set7 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set8 => sField_set8 !! This method is used for assignment operator - PROCEDURE, PASS(obj) :: set9 => sField_set9 + PROCEDURE, PASS(obj) :: Set9 => sField_set9 !! Set selected values using FEVariable - PROCEDURE, PASS(obj) :: set10 => sField_set10 + PROCEDURE, PASS(obj) :: Set10 => sField_set10 !! Set selected values using FEVariable - PROCEDURE, PASS(obj) :: set11 => sField_set11 + PROCEDURE, PASS(obj) :: Set11 => sField_set11 !! Set selected values using FEVariable - GENERIC, PUBLIC :: set => set1, set2, set3, set4, & - & set5, set6, set7, set8, set9, set10, set11 - GENERIC, PUBLIC :: ASSIGNMENT(=) => set8 - !! set values to a vector - PROCEDURE, PASS(obj) :: get1 => sField_get1 - !! get single entry - PROCEDURE, PASS(obj) :: get2 => sField_get2 - !! get all values in Real vector - PROCEDURE, PASS(obj) :: get3 => sField_get3 - !! get selected values - PROCEDURE, PASS(obj) :: get4 => sField_get4 - !! get values from triplet - PROCEDURE, PASS(obj) :: get5 => sField_get5 - PROCEDURE, PASS(obj) :: get6 => sField_get6 - PROCEDURE, PASS(obj) :: get7 => sField_get7 - !! get selected values in FEVariable - GENERIC, PUBLIC :: get => get1, get2, get3, get4, get5, get6, get7 - !! get the entries of scalar field - PROCEDURE, PASS(obj) :: sField_applyDirichletBC1 - PROCEDURE, PASS(obj) :: sField_applyDirichletBC2 - GENERIC, PUBLIC :: applyDirichletBC => & - & sField_applyDirichletBC1, & - & sField_applyDirichletBC2 + GENERIC, PUBLIC :: Set => Set1, Set2, Set3, Set4, & + & Set5, Set6, Set7, Set8, Set9, Set10, Set11 + GENERIC, PUBLIC :: ASSIGNMENT(=) => Set8 + !! Set values to a vector + PROCEDURE, PASS(obj) :: Get1 => sField_Get1 + !! Get single entry + PROCEDURE, PASS(obj) :: Get2 => sField_Get2 + !! Get all values in Real vector + PROCEDURE, PASS(obj) :: Get3 => sField_Get3 + !! Get selected values + PROCEDURE, PASS(obj) :: Get4 => sField_Get4 + !! Get values from triplet + PROCEDURE, PASS(obj) :: Get5 => sField_Get5 + PROCEDURE, PASS(obj) :: Get6 => sField_Get6 + PROCEDURE, PASS(obj) :: Get7 => sField_Get7 + !! Get selected values in FEVariable + GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, Get5, Get6, Get7 + !! Get the entries of scalar field + PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC1 + PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC2 + GENERIC, PUBLIC :: ApplyDirichletBC => & + & sField_ApplyDirichletBC1, & + & sField_ApplyDirichletBC2 !! PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => sField_Import END TYPE ScalarField_ +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + TYPE(ScalarField_), PARAMETER, PUBLIC :: & & TypeScalarField = ScalarField_(domains=NULL()) @@ -120,7 +124,7 @@ MODULE ScalarField_Class END TYPE ScalarFieldPointer_ !---------------------------------------------------------------------------- -! setScalarFieldParam@Constructor +! SetScalarFieldParam@Constructor !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -128,11 +132,15 @@ MODULE ScalarField_Class ! summary: Set the essential parameters INTERFACE - MODULE SUBROUTINE SetScalarFieldParam(param, name, engine, fieldType, comm, local_n, global_n) + MODULE SUBROUTINE SetScalarFieldParam(param, name, engine, & + & fieldType, comm, local_n, global_n) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: name + !! name of the variable CHARACTER(*), INTENT(IN) :: engine + !! name of the engine INTEGER(I4B), OPTIONAL, INTENT(IN) :: fieldType + !! field type INTEGER(I4B), OPTIONAL, INTENT(IN) :: comm !! communication group !! Only needed for parallel environment @@ -179,7 +187,7 @@ END SUBROUTINE sField_CheckEssentialParam MODULE SUBROUTINE sField_Initiate1(obj, param, dom) CLASS(ScalarField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom END SUBROUTINE sField_Initiate1 END INTERFACE @@ -208,7 +216,7 @@ END SUBROUTINE sField_Final INTERFACE MODULE FUNCTION sField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom TYPE(ScalarField_) :: ans END FUNCTION sField_Constructor1 END INTERFACE @@ -228,7 +236,7 @@ END FUNCTION sField_Constructor1 INTERFACE MODULE FUNCTION sField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom CLASS(ScalarField_), POINTER :: ans END FUNCTION sField_Constructor_1 END INTERFACE @@ -250,8 +258,8 @@ MODULE SUBROUTINE sField_Import(obj, hdf5, group, dom, domains) CLASS(ScalarField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE sField_Import END INTERFACE @@ -265,17 +273,17 @@ END SUBROUTINE sField_Import !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the single entry of the scalar field +! summary: This routine Sets the single entry of the scalar field INTERFACE - MODULE SUBROUTINE sField_set1(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE sField_Set1(obj, globalNode, VALUE, scale, & & addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set1 + END SUBROUTINE sField_Set1 END INTERFACE !---------------------------------------------------------------------------- @@ -284,15 +292,15 @@ END SUBROUTINE sField_set1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a scalar field +! summary: This routine Sets all the entries of a scalar field INTERFACE - MODULE SUBROUTINE sField_set2(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set2(obj, VALUE, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set2 + END SUBROUTINE sField_Set2 END INTERFACE !---------------------------------------------------------------------------- @@ -301,15 +309,15 @@ END SUBROUTINE sField_set2 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using a fortran vector +! summary: This routine Set all the entries by using a fortran vector INTERFACE - MODULE SUBROUTINE sField_set3(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set3(obj, VALUE, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set3 + END SUBROUTINE sField_Set3 END INTERFACE !---------------------------------------------------------------------------- @@ -318,16 +326,16 @@ END SUBROUTINE sField_set3 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE sField_set4(obj, globalNode, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set4(obj, globalNode, VALUE, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set4 + END SUBROUTINE sField_Set4 END INTERFACE !---------------------------------------------------------------------------- @@ -336,16 +344,16 @@ END SUBROUTINE sField_set4 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE sField_set5(obj, globalNode, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set5(obj, globalNode, VALUE, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set5 + END SUBROUTINE sField_Set5 END INTERFACE !---------------------------------------------------------------------------- @@ -354,10 +362,10 @@ END SUBROUTINE sField_set5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries using triplet +! summary: This routine Sets the selected entries using triplet INTERFACE - MODULE SUBROUTINE sField_set6(obj, istart, iend, stride, VALUE, & + MODULE SUBROUTINE sField_Set6(obj, istart, iend, stride, VALUE, & & scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -366,7 +374,7 @@ MODULE SUBROUTINE sField_set6(obj, istart, iend, stride, VALUE, & REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set6 + END SUBROUTINE sField_Set6 END INTERFACE !---------------------------------------------------------------------------- @@ -375,10 +383,10 @@ END SUBROUTINE sField_set6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the vector vals using triplet +! summary: Set the vector vals using triplet INTERFACE - MODULE SUBROUTINE sField_set7(obj, istart, iend, stride, VALUE, & + MODULE SUBROUTINE sField_Set7(obj, istart, iend, stride, VALUE, & & scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -387,7 +395,7 @@ MODULE SUBROUTINE sField_set7(obj, istart, iend, stride, VALUE, & REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set7 + END SUBROUTINE sField_Set7 END INTERFACE !---------------------------------------------------------------------------- @@ -399,10 +407,10 @@ END SUBROUTINE sField_set7 ! summary: used for assignment operator INTERFACE - MODULE SUBROUTINE sField_set8(obj, obj2) + MODULE SUBROUTINE sField_Set8(obj, obj2) CLASS(ScalarField_), INTENT(INOUT) :: obj CLASS(ScalarField_), INTENT(IN) :: obj2 - END SUBROUTINE sField_set8 + END SUBROUTINE sField_Set8 END INTERFACE !---------------------------------------------------------------------------- @@ -411,17 +419,17 @@ END SUBROUTINE sField_set8 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries using [[FEVariable_]] +! summary: This routine Sets the selected entries using [[FEVariable_]] INTERFACE - MODULE SUBROUTINE sField_set9(obj, globalNode, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set9(obj, globalNode, VALUE, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) TYPE(FEVariable_), INTENT(IN) :: VALUE !! Scalar, Nodal, FEVariable (Space or Constant) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set9 + END SUBROUTINE sField_Set9 END INTERFACE !---------------------------------------------------------------------------- @@ -433,12 +441,12 @@ END SUBROUTINE sField_set9 ! summary: obj=obj+scalar*obj2 INTERFACE - MODULE SUBROUTINE sField_set10(obj, obj2, scale, addContribution) + MODULE SUBROUTINE sField_Set10(obj, obj2, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj CLASS(ScalarField_), INTENT(IN) :: obj2 REAL(DFP), INTENT(IN) :: scale LOGICAL(LGT), INTENT(IN) :: addContribution - END SUBROUTINE sField_set10 + END SUBROUTINE sField_Set10 END INTERFACE !---------------------------------------------------------------------------- @@ -446,7 +454,7 @@ END SUBROUTINE sField_set10 !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE sField_set11(obj, ivar, idof, VALUE, ivar_value, & + MODULE SUBROUTINE sField_Set11(obj, ivar, idof, VALUE, ivar_value, & & idof_value, scale, addContribution) CLASS(ScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: ivar @@ -456,11 +464,11 @@ MODULE SUBROUTINE sField_set11(obj, ivar, idof, VALUE, ivar_value, & INTEGER(I4B), INTENT(IN) :: idof_value REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set11 + END SUBROUTINE sField_Set11 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -468,15 +476,15 @@ END SUBROUTINE sField_set11 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE sField_get1(obj, VALUE, globalNode) + MODULE SUBROUTINE sField_Get1(obj, VALUE, globalNode) CLASS(ScalarField_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode - END SUBROUTINE sField_get1 + END SUBROUTINE sField_Get1 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -484,14 +492,14 @@ END SUBROUTINE sField_get1 ! summary: This routine returns all the entries by using given scalar field INTERFACE - MODULE SUBROUTINE sField_get2(obj, VALUE) + MODULE SUBROUTINE sField_Get2(obj, VALUE) CLASS(ScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - END SUBROUTINE sField_get2 + END SUBROUTINE sField_Get2 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -499,15 +507,15 @@ END SUBROUTINE sField_get2 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE sField_get3(obj, VALUE, globalNode) + MODULE SUBROUTINE sField_Get3(obj, VALUE, globalNode) CLASS(ScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE sField_get3 + END SUBROUTINE sField_Get3 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -515,17 +523,17 @@ END SUBROUTINE sField_get3 ! summary: returns the value using triplet INTERFACE - MODULE SUBROUTINE sField_get4(obj, VALUE, istart, iend, stride) + MODULE SUBROUTINE sField_Get4(obj, VALUE, istart, iend, stride) CLASS(ScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - END SUBROUTINE sField_get4 + END SUBROUTINE sField_Get4 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -533,16 +541,16 @@ END SUBROUTINE sField_get4 ! summary: returns the selected values in FEVariable INTERFACE - MODULE SUBROUTINE sField_get5(obj, VALUE, globalNode) + MODULE SUBROUTINE sField_Get5(obj, VALUE, globalNode) CLASS(ScalarField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE !! Scalar Nodal FEVariable INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE sField_get5 + END SUBROUTINE sField_Get5 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -550,25 +558,25 @@ END SUBROUTINE sField_get5 ! summary: returns the selected values in FEVariable INTERFACE - MODULE SUBROUTINE sField_get6(obj, VALUE) + MODULE SUBROUTINE sField_Get6(obj, VALUE) CLASS(ScalarField_), INTENT(IN) :: obj CLASS(ScalarField_), INTENT(INOUT) :: VALUE - END SUBROUTINE sField_get6 + END SUBROUTINE sField_Get6 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE sField_get7(obj, ivar, idof, VALUE, ivar_value, idof_value) + MODULE SUBROUTINE sField_Get7(obj, ivar, idof, VALUE, ivar_value, idof_value) CLASS(ScalarField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof INTEGER(I4B), INTENT(IN) :: ivar_value INTEGER(I4B), INTENT(IN) :: idof_value - END SUBROUTINE sField_get7 + END SUBROUTINE sField_Get7 END INTERFACE !---------------------------------------------------------------------------- From 728427481faafddeb00b023552a582a79db7966e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 10:20:18 +0900 Subject: [PATCH 004/117] Improvement in CMake Fixes #163 --- cmake/Compiler.cmake | 29 ++++++++++++++++++++++- cmake/Config.cmake.in | 2 -- cmake/addGmsh-old.cmake | 35 ++++++++++++++++++++++++++++ cmake/addGmsh.cmake | 30 ++++++++++++++++-------- cmake/targetCompileDefs.cmake | 4 ++-- cmake/targetLinkLibs.cmake | 43 ----------------------------------- install.py | 4 ++-- 7 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 cmake/addGmsh-old.cmake diff --git a/cmake/Compiler.cmake b/cmake/Compiler.cmake index b3a46043b..067043f78 100644 --- a/cmake/Compiler.cmake +++ b/cmake/Compiler.cmake @@ -31,7 +31,34 @@ ENDIF() IF (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU" OR Fortran_COMPILER_NAME MATCHES "gfortran*") LIST(APPEND FORTRAN_FLAGS "-ffree-form" "-ffree-line-length-none" "-std=f2018" "-fimplicit-none" ) LIST(APPEND FORTRAN_FLAGS_RELEASE "-O3" ) - LIST(APPEND FORTRAN_FLAGS_DEBUG "-fbounds-check" "-g" "-fbacktrace" "-Wextra" "-Wall" "-fprofile-arcs" "-ftest-coverage" "-Wimplicit-interface" ) + + IF(APPLE) + LIST( + APPEND + FORTRAN_FLAGS_DEBUG + "-fbounds-check" + "-g" + "-fbacktrace" + "-Wextra" + "-Wall" + # "-fprofile-arcs" + "-ftest-coverage" + "-Wimplicit-interface" + ) + ELSE() + LIST( + APPEND + FORTRAN_FLAGS_DEBUG + "-fbounds-check" + "-g" + "-fbacktrace" + "-Wextra" + "-Wall" + # "-fprofile-arcs" + "-ftest-coverage" + "-Wimplicit-interface" + ) + ENDIF() ELSEIF(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel" OR Fortran_COMPILER_NAME MATCHES "ifort*") LIST(APPEND FORTRAN_FLAGS "-r8" "-W1") diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in index 53bcc9b97..a8049d31c 100644 --- a/cmake/Config.cmake.in +++ b/cmake/Config.cmake.in @@ -28,8 +28,6 @@ # find_package(easifemBase 1.0.0 CONFIG REQUIRED) # # The following variables can be set to guide the search for this package: -# -# @PACKAGE_INIT@ diff --git a/cmake/addGmsh-old.cmake b/cmake/addGmsh-old.cmake new file mode 100644 index 000000000..897195819 --- /dev/null +++ b/cmake/addGmsh-old.cmake @@ -0,0 +1,35 @@ +# 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 +# +#GMSH SDK +IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) + OPTION( USE_GMSH_SDK OFF ) + IF( USE_GMSH_SDK ) + LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) + IF( UNIX ) + IF(APPLE) + SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) + ELSE() + # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) + SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) + ENDIF() + ENDIF() + TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) + MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) + ELSE() + MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) + ENDIF() +ENDIF() diff --git a/cmake/addGmsh.cmake b/cmake/addGmsh.cmake index 897195819..39cecb6e8 100644 --- a/cmake/addGmsh.cmake +++ b/cmake/addGmsh.cmake @@ -19,15 +19,27 @@ IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) OPTION( USE_GMSH_SDK OFF ) IF( USE_GMSH_SDK ) LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) - IF( UNIX ) - IF(APPLE) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) - ELSE() - # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) - ENDIF() - ENDIF() - TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) + FIND_PACKAGE(PkgConfig REQUIRED) + FIND_LIBRARY(GMSH_LIBRARY + NAMES gmsh gmsh.4.12 + PATHS "$ENV{CONDA_PREFIX}/lib" "/opt/homebrew/lib" ) + # PATHS "/opt/homebrew/lib" ) + SET(GMSH_LIBRARIES ${GMSH_LIBRARY}) + + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS( + GMSH DEFAULT_MSG + GMSH_LIBRARIES + ) + + # SET(GMSH_LIBRARIES "$ENV{CONDA_PREFIX}/lib/libgmsh.so") + + TARGET_LINK_LIBRARIES( + ${PROJECT_NAME} + PUBLIC + ${GMSH_LIBRARIES} + ) + MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) ELSE() MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) diff --git a/cmake/targetCompileDefs.cmake b/cmake/targetCompileDefs.cmake index f7c9ae517..b8c68788e 100644 --- a/cmake/targetCompileDefs.cmake +++ b/cmake/targetCompileDefs.cmake @@ -38,10 +38,10 @@ ENDIF() LIST( APPEND TARGET_COMPILE_DEF "-D${CMAKE_HOST_SYSTEM_NAME}_SYSTEM" ) #DEFINE DEBUG -IF( $ ) +IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug") LIST( APPEND TARGET_COMPILE_DEF "-DDEBUG_VER" ) ENDIF() #ADD TO PROJECT TARGET_COMPILE_DEFINITIONS( ${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_DEF} ) -MESSAGE( STATUS "COMPILE DEFINITIONS USED ARE ${TARGET_COMPILE_DEF}") \ No newline at end of file +MESSAGE( STATUS "COMPILE DEFINITIONS USED ARE ${TARGET_COMPILE_DEF}") diff --git a/cmake/targetLinkLibs.cmake b/cmake/targetLinkLibs.cmake index fb29a3ee5..024a1e8c1 100644 --- a/cmake/targetLinkLibs.cmake +++ b/cmake/targetLinkLibs.cmake @@ -16,49 +16,6 @@ # # -# Link libs to the project - -#.................................................................... -# -#.................................................................... - -FUNCTION(FIND_EASIFEM_DEPENDENCY EXT_PKG_LIST) - FOREACH(p ${EXT_PKG_LIST}) - FIND_PACKAGE( ${p} REQUIRED ) - IF( ${p}_FOUND ) - MESSAGE(STATUS "FOUND ${p}") - ELSE() - MESSAGE(ERROR "NOT FOUND ${p}") - ENDIF() - ENDFOREACH() -ENDFUNCTION(FIND_EASIFEM_DEPENDENCY) - -#.................................................................... -# -#.................................................................... - -FUNCTION(LINK_EASIFEM_DEPENDENCY EXT_PKG_LIST PROJECT_NAME) - FOREACH(p ${EXT_PKG_LIST}) - TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${p}::${p} ) - ENDFOREACH() -ENDFUNCTION(LINK_EASIFEM_DEPENDENCY) - -#.................................................................... -# -#.................................................................... - -IF( ${PROJECT_NAME} MATCHES "easifemBase" ) - IF( USE_LAPACK95 ) - LIST(APPEND EXT_PKGS LAPACK95) - LIST( APPEND TARGET_COMPILE_DEF "-DUSE_LAPACK95" ) - ENDIF() - - LIST(APPEND EXT_PKGS Sparsekit) - - FIND_EASIFEM_DEPENDENCY( "${EXT_PKGS}" ) - LINK_EASIFEM_DEPENDENCY( "${EXT_PKGS}" "${PROJECT_NAME}" ) -ENDIF() - #.................................................................... # #.................................................................... diff --git a/install.py b/install.py index c81816614..4e999f3d8 100755 --- a/install.py +++ b/install.py @@ -20,8 +20,8 @@ else: cmake_def = "" cmake_def += '-G "Ninja"' - cmake_def += " -D USE_GMSH_SDK:BOOL=OFF" - cmake_def += " -D CMAKE_BUILD_TYPE:STRING=Release" + cmake_def += " -D USE_GMSH_SDK:BOOL=ON" + cmake_def += " -D CMAKE_BUILD_TYPE=Debug" cmake_def += " -D BUILD_SHARED_LIBS:BOOL=ON" cmake_def += " -D CMAKE_INSTALL_PREFIX:PATH=${EASIFEM_CLASSES}" print("CMAKE DEF : ", cmake_def) From 28f68f34d9dcba85c65cf5378a4ad25484765c07 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 10:50:55 +0900 Subject: [PATCH 005/117] Toml support in easifem Fixes #169 --- src/modules/Toml/CMakeLists.txt | 22 ++ src/modules/Toml/src/TomlUtility.F90 | 302 ++++++++++++++++++ src/submodules/Toml/CMakeLists.txt | 22 ++ .../Toml/src/TomlUtility@GetMethods.F90 | 199 ++++++++++++ 4 files changed, 545 insertions(+) create mode 100644 src/modules/Toml/CMakeLists.txt create mode 100644 src/modules/Toml/src/TomlUtility.F90 create mode 100644 src/submodules/Toml/CMakeLists.txt create mode 100644 src/submodules/Toml/src/TomlUtility@GetMethods.F90 diff --git a/src/modules/Toml/CMakeLists.txt b/src/modules/Toml/CMakeLists.txt new file mode 100644 index 000000000..c3395ef97 --- /dev/null +++ b/src/modules/Toml/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/TomlUtility.F90 +) diff --git a/src/modules/Toml/src/TomlUtility.F90 b/src/modules/Toml/src/TomlUtility.F90 new file mode 100644 index 000000000..8fc0515d1 --- /dev/null +++ b/src/modules/Toml/src/TomlUtility.F90 @@ -0,0 +1,302 @@ +! 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 TomlUtility +USE GlobalData +USE tomlf, ONLY: toml_table +USE TxtFile_Class +USE ExceptionHandler_Class, ONLY: e +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "TomlUtility" +PUBLIC :: GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int8_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT8), ALLOCATABLE, INTENT(OUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int8_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int16_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT16), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int16_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int32_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT32), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int32_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int64_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT64), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int64_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real32_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL32), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real32_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue integer vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real64_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL64), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real64_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int8_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT8), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int8_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int16_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT16), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int16_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int32_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT32), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int32_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int64_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT64), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int64_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real32_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL32), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real32_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real64_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL64), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real64_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate table from toml file + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_from_file(table, afile) + TYPE(toml_table), ALLOCATABLE, INTENT(INOUT) :: table + TYPE(TxtFile_), INTENT(INOUT) :: afile + END SUBROUTINE toml_get_from_file +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate table from toml file + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_from_filename(table, filename) + TYPE(toml_table), ALLOCATABLE, INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: filename + END SUBROUTINE toml_get_from_filename +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE TomlUtility diff --git a/src/submodules/Toml/CMakeLists.txt b/src/submodules/Toml/CMakeLists.txt new file mode 100644 index 000000000..7917e32bf --- /dev/null +++ b/src/submodules/Toml/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/TomlUtility@GetMethods.F90 +) diff --git a/src/submodules/Toml/src/TomlUtility@GetMethods.F90 b/src/submodules/Toml/src/TomlUtility@GetMethods.F90 new file mode 100644 index 000000000..6a6ebcd87 --- /dev/null +++ b/src/submodules/Toml/src/TomlUtility@GetMethods.F90 @@ -0,0 +1,199 @@ +! 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(TomlUtility) GetMethods +USE String_Class +USE TxtFile_Class +USE BaseMethod +USE tomlf, ONLY: & + & toml_error, & + & toml_load, & + & toml_parser_config, & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_context, & + & toml_terminal, & + & toml_load, & + & toml_array, & + & toml_stat +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int8_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int8_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int16_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int16_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int32_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int32_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int64_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int64_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real32_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_real32_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real64_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_real64_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int8_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int8_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int16_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int16_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int32_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int32_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int64_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int64_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real32_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_real32_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real64_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_real64_r2 + +!---------------------------------------------------------------------------- +! toml_get_from_file +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_from_file +CHARACTER(*), PARAMETER :: myName = "toml_get_from_file()" +LOGICAL(LGT) :: isNotOpen, isNotRead +LOGICAL(LGT), PARAMETER :: color = .TRUE. +INTEGER(I4B), PARAMETER :: detail = 1 +TYPE(toml_error), ALLOCATABLE :: error +TYPE(toml_context) :: context +TYPE(toml_terminal) :: terminal + +terminal = toml_terminal(color) +isNotOpen = .NOT. afile%IsOpen() +isNotRead = .NOT. afile%IsRead() + +IF (isNotRead .OR. isNotOpen) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The file is not open or does not have '// & + & 'the access to read!') +END IF + +CALL toml_load(table, & + & afile%GetUnitNo(), & + & context=context, & + & config=toml_parser_config(color=terminal, context_detail=detail), & + & error=error & + & ) + +IF (ALLOCATED(error)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & + & ' with following message: '//CHAR_LF//error%message) +END IF + +END PROCEDURE toml_get_from_file + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_from_filename +CHARACTER(*), PARAMETER :: myName = "toml_get_from_filename()" +LOGICAL(LGT), PARAMETER :: color = .TRUE. +INTEGER(I4B), PARAMETER :: detail = 1 +TYPE(toml_error), ALLOCATABLE :: error +TYPE(toml_context) :: context +TYPE(toml_terminal) :: terminal + +terminal = toml_terminal(color) +CALL toml_load(table, & + & filename, & + & context=context, & + & config=toml_parser_config(color=terminal, context_detail=detail), & + & error=error & + & ) + +IF (ALLOCATED(error)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & + & ' with following message: '//CHAR_LF//error%message) +END IF + +END PROCEDURE toml_get_from_filename + +END SUBMODULE GetMethods From 431def9b1aec6b1a75d0f5bb8f5e542c80c99c86 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 11:05:53 +0900 Subject: [PATCH 006/117] Enhancements in AbstractBoundaryCondition_ Fixes #91 --- src/modules/AbstractBC/CMakeLists.txt | 19 +- src/modules/AbstractBC/src/AbstractBC.toml | 61 ++++ .../AbstractBC/src/AbstractBC_Class.F90 | 288 ++++++++++++------ .../AbstractBC_Class@ConstructorMethods.F90 | 241 +++++++-------- .../src/AbstractBC_Class@GetMethods.F90 | 29 +- .../src/AbstractBC_Class@IOMethods.F90 | 282 +++++++++++++++-- .../src/AbstractBC_Class@SetMethods.F90 | 280 ++++++++--------- 7 files changed, 795 insertions(+), 405 deletions(-) create mode 100644 src/modules/AbstractBC/src/AbstractBC.toml diff --git a/src/modules/AbstractBC/CMakeLists.txt b/src/modules/AbstractBC/CMakeLists.txt index 47e087846..ebba19c43 100644 --- a/src/modules/AbstractBC/CMakeLists.txt +++ b/src/modules/AbstractBC/CMakeLists.txt @@ -1,5 +1,22 @@ +# 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}/AbstractBC_Class.F90 -) \ No newline at end of file +) diff --git a/src/modules/AbstractBC/src/AbstractBC.toml b/src/modules/AbstractBC/src/AbstractBC.toml new file mode 100644 index 000000000..5d7f409b5 --- /dev/null +++ b/src/modules/AbstractBC/src/AbstractBC.toml @@ -0,0 +1,61 @@ +[bc] +name="DirichletBC" +idof=1 +nodalValueType="Constant" # Time, SpaceTime, Space +useFunction=false +isNormal=false +isTangent=false +useExternal=false +value=20.0 # when nodalValueType=Constant +# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Space +# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Time +# value=[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]] # SpaceTime +spaceFunction="lua script f(x)" +timeFunction="lua script f(t)" +spaceTimeFunction="lua script f(x, t)" + +[bc.boundary] +isSelectionByMeshID = false +isSelectionByElemNum = false +isSelectionByBox = false +isSelectionByNodeNum = false + +[bc.boundary.meshID] +point = [1,2,3] # "filename.txt" +line = [1,2,3,4] # "filename.txt" +surface = [1,2,3] # "filename.txt" +volume = [1,2,3] # "filename.txt" + +[bc.boundary.box] +point = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +line = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +surface = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +volume = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +[bc.boundary.elemNum] +point = [1,2,3] +line = [1,2,3] +surface=[1,2,3] +volume=[1,2,3] + +[bc.boundary.nodeNum] +point = [1,2,3] +line = [1,2,3] +surface=[1,2,3] +volume=[1,2,3] + diff --git a/src/modules/AbstractBC/src/AbstractBC_Class.F90 b/src/modules/AbstractBC/src/AbstractBC_Class.F90 index a044df100..ca1e9526f 100644 --- a/src/modules/AbstractBC/src/AbstractBC_Class.F90 +++ b/src/modules/AbstractBC/src/AbstractBC_Class.F90 @@ -13,7 +13,6 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see -! MODULE AbstractBC_Class USE GlobalData @@ -24,9 +23,28 @@ MODULE AbstractBC_Class USE Domain_Class USE HDF5File_Class USE FPL, ONLY: ParameterList_ +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractBC_Class" +CHARACTER(*), PARAMETER :: default_name = "AbstractBC" +INTEGER(I4B), PARAMETER :: default_idof = 0_I4B +INTEGER(I4B), PARAMETER :: default_nodalValueType = -1_I4B +CHARACTER(*) , PARAMETER :: default_nodalValueType_char = "NONE" +LOGICAL(LGT), PARAMETER :: default_useFunction = .FALSE. +LOGICAL(LGT), PARAMETER :: default_isNormal = .FALSE. +LOGICAL(LGT), PARAMETER :: default_isTangent = .FALSE. +LOGICAL(LGT), PARAMETER :: default_useExternal = .FALSE. + +PUBLIC :: AbstractBC_ +PUBLIC :: AbstractBCPointer_ +PUBLIC :: AbstractBCDeallocate +PUBLIC :: AbstractBCcheckEssentialParam +PUBLIC :: SetAbstractBCParam +PUBLIC :: AbstractBCInitiate +PUBLIC :: AbstractBCImportFromToml +PUBLIC :: AbstractBCImportParamFromToml !---------------------------------------------------------------------------- ! AbstractBC_ @@ -38,23 +56,23 @@ MODULE AbstractBC_Class TYPE, ABSTRACT :: AbstractBC_ LOGICAL(LGT) :: isInitiated = .FALSE. - !! + !! It is true if the object is initiated TYPE(String) :: name !! name of boundary condition - INTEGER(I4B) :: idof = 0 + INTEGER(I4B) :: idof = default_idof !! degree of freedom number - INTEGER(I4B) :: nodalValueType = -1 + INTEGER(I4B) :: nodalValueType = default_nodalValueType !! Constant !! Space !! Time !! SpaceTime - LOGICAL(LGT) :: useFunction = .FALSE. + LOGICAL(LGT) :: useFunction = default_useFunction !! True if the boundary condition is analytical - LOGICAL(LGT) :: isNormal = .FALSE. + LOGICAL(LGT) :: isNormal = default_isNormal !! True if the boundary condition is normal to the boundary - LOGICAL(LGT) :: isTangent = .FALSE. + LOGICAL(LGT) :: isTangent = default_isTangent !! True if the boundary condition is tangent to the boundary - LOGICAL(LGT) :: useExternal = .FALSE. + LOGICAL(LGT) :: useExternal = default_useExternal !! if true then nodal values are used externally !! depending upon the context. !! Basically we do not use the nodal value stored in the @@ -77,25 +95,46 @@ MODULE AbstractBC_Class !! Domain CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => bc_Deallocate - PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID - PROCEDURE, PUBLIC, PASS(obj) :: Get => bc_Get - PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction - PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo - PROCEDURE, PUBLIC, PASS(obj) :: & - & CheckEssentialParam => bc_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & bc_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => bc_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => bc_Export PROCEDURE, PUBLIC, PASS(obj) :: Display => bc_Display - PROCEDURE, PUBLIC, PASS(obj) :: isUseFunction => bc_isUseFunction - !! Returns true if the useFunction is true + PROCEDURE, PASS(obj) :: ImportFromToml1 => bc_ImportFromToml1 + PROCEDURE, PASS(obj) :: ImportFromToml2 => bc_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & + & ImportFromToml2 + !! Import abstract kernel from toml + PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & + & bc_ImportParamFromToml + + ! SET: + ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: Set => bc_Set + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID + PROCEDURE, PUBLIC, PASS(obj) :: Get1 => bc_Get + PROCEDURE, PUBLIC, PASS(obj) :: Get2 => bc_GetFEVar + GENERIC, PUBLIC :: Get => Get1, Get2 + PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction + PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo PROCEDURE, PUBLIC, PASS(obj) :: GetQuery => bc_GetQuery + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => bc_GetQuery + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: isUseFunction => bc_isUseFunction + !! Returns true if the useFunction is true END TYPE AbstractBC_ -PUBLIC :: AbstractBC_ - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -104,72 +143,32 @@ MODULE AbstractBC_Class CLASS(AbstractBC_), POINTER :: ptr => NULL() END TYPE AbstractBCPointer_ -PUBLIC :: AbstractBCPointer_ - !---------------------------------------------------------------------------- ! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- -INTERFACE - MODULE SUBROUTINE bc_CheckEssentialParam(obj, param) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE bc_CheckEssentialParam -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(MeshSelection_), INTENT(IN) :: boundary - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - !> author: Vikas Sharma, Ph. D. -! date: 2023-02-12 -! summary: Deallocate data +! date: 2023-11-14 +! summary: Check essential parameters -INTERFACE - MODULE SUBROUTINE bc_Deallocate(obj) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - END SUBROUTINE bc_Deallocate -END INTERFACE - -INTERFACE AbstractBCDeallocate - MODULE PROCEDURE bc_Deallocate -END INTERFACE AbstractBCDeallocate - -PUBLIC :: AbstractBCDeallocate - -!---------------------------------------------------------------------------- -! AbstractBCcheckEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE AbstractBCcheckEssentialParam(obj, param, prefix) +INTERFACE AbstractBCcheckEssentialParam + MODULE SUBROUTINE bc_CheckEssentialParam(obj, param, prefix) CLASS(AbstractBC_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractBCcheckEssentialParam -END INTERFACE - -PUBLIC :: AbstractBCcheckEssentialParam + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE bc_CheckEssentialParam +END INTERFACE AbstractBCcheckEssentialParam !---------------------------------------------------------------------------- ! SetAbstractBCParam@ConstructorMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Set abstract boundary condition parameters + INTERFACE - MODULE SUBROUTINE setAbstractBCParam(param, prefix, & + MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & & name, idof, nodalValueType, useFunction, isNormal, isTangent, & & useExternal) TYPE(ParameterList_), INTENT(INOUT) :: param @@ -195,31 +194,48 @@ MODULE SUBROUTINE setAbstractBCParam(param, prefix, & !! default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useExternal !! default is false - END SUBROUTINE setAbstractBCParam + END SUBROUTINE SetAbstractBCParam END INTERFACE -PUBLIC :: setAbstractBCParam - !---------------------------------------------------------------------------- -! AbstractBCInitiate@ConstructorMethods +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- -INTERFACE - MODULE SUBROUTINE AbstractBCInitiate(obj, param, prefix, boundary, dom) +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Initiate abstract boundary condition + +INTERFACE AbstractBCInitiate + MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) CLASS(AbstractBC_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - CHARACTER(*), INTENT(IN) :: prefix TYPE(MeshSelection_), INTENT(IN) :: boundary CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE AbstractBCInitiate -END INTERFACE + END SUBROUTINE bc_Initiate +END INTERFACE AbstractBCInitiate -PUBLIC :: AbstractBCInitiate +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-02-12 +! summary: Deallocate data + +INTERFACE AbstractBCDeallocate + MODULE SUBROUTINE bc_Deallocate(obj) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + END SUBROUTINE bc_Deallocate +END INTERFACE AbstractBCDeallocate !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Import AbstractBC from HDF5File + INTERFACE MODULE SUBROUTINE bc_Import(obj, hdf5, group, dom) CLASS(AbstractBC_), INTENT(INOUT) :: obj @@ -245,6 +261,58 @@ MODULE SUBROUTINE bc_Export(obj, hdf5, group) END SUBROUTINE bc_Export END INTERFACE +!---------------------------------------------------------------------------- +! ImportParamFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param by reading the toml table + +INTERFACE AbstractBCImportParamFromToml + MODULE SUBROUTINE bc_ImportParamFromToml(obj, param, table) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE bc_ImportParamFromToml +END INTERFACE AbstractBCImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE AbstractBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + CLASS(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE bc_ImportFromToml1 +END INTERFACE AbstractBCImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE AbstractBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & + & filename, printToml) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + CLASS(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE bc_ImportFromToml2 +END INTERFACE AbstractBCImportFromToml + !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- @@ -294,6 +362,27 @@ MODULE SUBROUTINE bc_Get(obj, nodeNum, nodalValue, times) END SUBROUTINE bc_Get END INTERFACE +!---------------------------------------------------------------------------- +! Get@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-02-12 +! summary: Get the node number and nodal value + +INTERFACE + MODULE SUBROUTINE bc_GetFEVar(obj, fevar, globalNode, & + & spaceQuadPoints, timeQuadPoints, atime, timeVec) + CLASS(AbstractBC_), INTENT(IN) :: obj + TYPE(FEVariable_), INTENT(INOUT) :: fevar + INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceQuadPoints(:, :) + REAL(DFP), OPTIONAL, INTENT(IN) :: timeQuadPoints(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: atime + REAL(DFP), OPTIONAL, INTENT(IN) :: timeVec(:) + END SUBROUTINE bc_GetFEVar +END INTERFACE + !---------------------------------------------------------------------------- ! GetFromFunction@GetMethods !---------------------------------------------------------------------------- @@ -327,10 +416,10 @@ END FUNCTION bc_GetDOFNo !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_isUseFunction(obj) RESULT(ans) + MODULE PURE FUNCTION bc_IsUseFunction(obj) RESULT(ans) CLASS(AbstractBC_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION bc_isUseFunction + END FUNCTION bc_IsUseFunction END INTERFACE !---------------------------------------------------------------------------- @@ -338,20 +427,20 @@ END FUNCTION bc_isUseFunction !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE bc_Set(obj, ConstantNodalValue, SpaceNodalValue, & - & TimeNodalValue, SpaceTimeNodalValue, SpaceFunction, TimeFunction, & - & SpaceTimeFunction) + MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & + & timeNodalValue, spaceTimeNodalValue, spaceFunction, timeFunction, & + & spaceTimeFunction) CLASS(AbstractBC_), INTENT(INOUT) :: obj - REAL(DFP), OPTIONAL, INTENT(IN) :: ConstantNodalValue - REAL(DFP), OPTIONAL, INTENT(IN) :: SpaceNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: TimeNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: SpaceTimeNodalValue(:, :) + REAL(DFP), OPTIONAL, INTENT(IN) :: constantNodalValue + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) PROCEDURE(iface_SpaceTimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & SpaceTimeFunction + & spaceTimeFunction PROCEDURE(iface_SpaceFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & SpaceFunction + & spaceFunction PROCEDURE(iface_TimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & TimeFunction + & timeFunction END SUBROUTINE bc_Set END INTERFACE @@ -379,4 +468,19 @@ MODULE PURE SUBROUTINE bc_GetQuery(obj, isInitiated, & END SUBROUTINE bc_GetQuery END INTERFACE +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) + CLASS(AbstractBC_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bc_GetPrefix +END INTERFACE + END MODULE AbstractBC_Class diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 index 4608ec207..352179b99 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 @@ -17,29 +17,10 @@ SUBMODULE(AbstractBC_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" -CALL e%raiseError(modName//'::'//myName//' - '// & - & 'This routine should be implemented by children of AbstractBC_') -END PROCEDURE bc_CheckEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_Initiate -CHARACTER(*), PARAMETER :: myName = "bc_Initiate" -CALL e%raiseError(modName//'::'//myName//' - '// & - & 'This routine should be implemented by children of AbstractBC_') -END PROCEDURE bc_Initiate - !---------------------------------------------------------------------------- ! Deallocate !---------------------------------------------------------------------------- @@ -65,165 +46,153 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractBCcheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "AbstractBCcheckEssentialParam" +MODULE PROCEDURE bc_checkessentialparam +CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" INTEGER(I4B) :: ii -INTEGER(I4B), PARAMETER :: maxEssentialParam = 7 -TYPE(String) :: essentialParam(maxEssentialParam) - -essentialParam(1) = prefix//"/name" -essentialParam(2) = prefix//"/idof" -essentialParam(3) = prefix//"/nodalValueType" -essentialParam(4) = prefix//"/useFunction" -essentialParam(5) = prefix//"/isNormal" -essentialParam(6) = prefix//"/isTangent" -essentialParam(7) = prefix//"/useExternal" - -DO ii = 1, maxEssentialParam - IF (.NOT. param%isPresent(key=TRIM(essentialParam(ii)%chars()))) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & TRIM(essentialParam(ii)%chars())//' should be present in param') - END IF -END DO +TYPE(String), ALLOCATABLE :: essentialParam(:) +TYPE(String) :: astr, prefix0 -END PROCEDURE AbstractBCcheckEssentialParam +IF (PRESENT(prefix)) THEN + prefix0 = prefix +ELSE + prefix0 = obj%GetPrefix() +END IF + +astr = "/name/idof/nodalValueType/useFunction/isNormal/isTangent/useExternal" + +CALL astr%Split(essentialParam, sep="/") +CALL CheckEssentialParam(obj=param, & + & keys=essentialParam, & + & prefix=prefix0%chars(), & + & myName=myName, & + & modName=modName) +!NOTE: CheckEssentialParam param is defined in easifemClasses FPL_Method + +IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" + END DO + DEALLOCATE (essentialParam) +END IF +astr = "" +prefix0 = "" +END PROCEDURE bc_CheckEssentialParam !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE setAbstractBCParam -INTEGER(I4B) :: ierr -CHARACTER(*), PARAMETER :: myName = "setAbstractBCParam" +MODULE PROCEDURE SetAbstractBCParam +CHARACTER(*), PARAMETER :: myName = "SetAbstractBCParam()" -IF (PRESENT(name)) THEN - ierr = param%set(key=TRIM(prefix)//"/name", VALUE=TRIM(name)) -ELSE - ierr = param%set(key=TRIM(prefix)//"/name", VALUE="AbstractBC") -END IF +CALL Set(param, datatype="char", prefix=prefix, key="name", & + & VALUE=input(option=name, default=default_name)) -IF (PRESENT(idof)) THEN - ierr = param%set(key=TRIM(prefix)//"/idof", VALUE=idof) -ELSE - ierr = param%set(key=TRIM(prefix)//"/idof", VALUE=0_I4B) -END IF +CALL Set(param, datatype=0_I4B, prefix=prefix, key="idof", & + & VALUE=input(option=idof, default=default_idof)) -IF (PRESENT(nodalValueType)) THEN - ierr = param%set(key=TRIM(prefix)//"/nodalValueType", VALUE=nodalValueType) -ELSE - ierr = param%set(key=TRIM(prefix)//"/nodalValueType", VALUE=-1_I4B) -END IF +CALL Set(param, datatype=0_I4B, prefix=prefix, key="nodalValueType", & + & VALUE=input(option=nodalValueType, default=default_nodalValueType)) -IF (PRESENT(useFunction)) THEN - ierr = param%set(key=TRIM(prefix)//"/useFunction", VALUE=useFunction) -ELSE - ierr = param%set(key=TRIM(prefix)//"/useFunction", VALUE=.FALSE.) -END IF +CALL Set(param, datatype=.TRUE., prefix=prefix, key="useFunction", & + & VALUE=input(option=useFunction, default=default_useFunction)) -IF (PRESENT(isNormal)) THEN - ierr = param%set(key=TRIM(prefix)//"/isNormal", VALUE=isNormal) - IF (PRESENT(idof)) THEN - IF (idof .GT. 0 .AND. isNormal) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'When isNormal is true, idof cannot be greater than 0') - END IF - END IF -ELSE - ierr = param%set(key=TRIM(prefix)//"/isNormal", VALUE=.FALSE.) -END IF +CALL Set(param, datatype=.TRUE., prefix=prefix, key="isNormal", & + & VALUE=input(option=isNormal, default=default_isNormal)) + +CALL Set(param, datatype=.TRUE., prefix=prefix, key="isTangent", & + & VALUE=input(option=isTangent, default=default_isTangent)) -IF (PRESENT(isTangent)) THEN - ierr = param%set(key=TRIM(prefix)//"/isTangent", VALUE=isTangent) - IF (PRESENT(idof)) THEN - IF (idof .GT. 0 .AND. isTangent) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'When isTangent is true, idof cannot be greater than 0') - END IF +CALL Set(param, datatype=.TRUE., prefix=prefix, key="useExternal", & + & VALUE=input(option=useExternal, default=default_useExternal)) + +IF (PRESENT(isNormal) .AND. PRESENT(idof)) THEN + IF (idof .GT. 0 .AND. isNormal) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When isNormal is true, '// & + & 'idof CANNOT be greater than 0.') END IF -ELSE - ierr = param%set(key=TRIM(prefix)//"/isTangent", VALUE=.FALSE.) END IF -IF (PRESENT(useExternal)) THEN - ierr = param%set(key=TRIM(prefix)//"/useExternal", VALUE=useExternal) -ELSE - ierr = param%set(key=TRIM(prefix)//"/useExternal", VALUE=.FALSE.) +IF (PRESENT(isTangent) .AND. PRESENT(idof)) THEN + IF (idof .GT. 0 .AND. isTangent) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When isTangent is true, '// & + & 'idof cannot be greater than 0.') + END IF END IF -END PROCEDURE setAbstractBCParam +END PROCEDURE SetAbstractBCParam !---------------------------------------------------------------------------- -! AbstractBCInitiate +! Initiate !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractBCInitiate -CHARACTER(*), PARAMETER :: myName = "AbstractBCInitiate" -CHARACTER(:), ALLOCATABLE :: char_var -INTEGER(I4B) :: ierr +MODULE PROCEDURE bc_Initiate +CHARACTER(*), PARAMETER :: myName = "bc_Initiate()" +LOGICAL(LGT) :: isSelectionByMeshID, abool +TYPE(String) :: prefix -IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'AbstractBC_ object is already initiated') -END IF +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +prefix = obj%GetPrefix() +CALL obj%DEALLOCATE() -CALL obj%checkEssentialParam(param=param) +CALL obj%CheckEssentialParam(param=param, prefix=prefix%chars()) obj%isInitiated = .TRUE. obj%boundary = boundary obj%dom => dom -! + ! name -! -ALLOCATE (CHARACTER(param%DataSizeInBytes( & - & key=TRIM(prefix)//"/name")) :: char_var) -ierr = param%get(key=TRIM(prefix)//"/name", VALUE=char_var) -obj%name = char_var -DEALLOCATE (char_var) -! +CALL GetValue(obj=param, prefix=prefix%chars(), key="name", VALUE=obj%name) + ! idof -! -ierr = param%get(key=TRIM(prefix)//"/idof", VALUE=obj%idof) -! +CALL GetValue(obj=param, prefix=prefix%chars(), key="idof", VALUE=obj%idof) + ! nodalValueType -! -ierr = param%get(key=TRIM(prefix)//"/nodalValueType", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="nodalValueType", & & VALUE=obj%nodalValueType) -! + ! useFunction -! -ierr = param%get(key=TRIM(prefix)//"/useFunction", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="useFunction", & & VALUE=obj%useFunction) -! + ! isNormal -! -ierr = param%get(key=TRIM(prefix)//"/isNormal", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="isNormal", & & VALUE=obj%isNormal) -! + ! isTangent -! -ierr = param%get(key=TRIM(prefix)//"/isTangent", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="isTangent", & & VALUE=obj%isTangent) -! + ! useExternal -! -ierr = param%get(key=TRIM(prefix)//"/useExternal", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="useExternal", & & VALUE=obj%useExternal) -! + ! check -! -IF (boundary%isSelectionByMeshID & - & .AND. (.NOT. obj%useFunction) & - & .AND. (.NOT. obj%useExternal)) THEN - IF (obj%nodalValueType .NE. Constant) THEN - CALL e%raiseWarning(modName//'::'//myName//" - "// & - & "When meshSelection is by MeshID & - & and `useFunction` is false, then & - & `nodalValueType` in `AbstractBC_` & - & object should be Constant.") - END IF +CALL boundary%GetParam(isSelectionByMeshID=isSelectionByMeshID) +abool = boundary%isSelectionByMeshID & + & .AND. (.NOT. obj%useFunction) & + & .AND. (.NOT. obj%useExternal) & + & .AND. (obj%nodalValueType .NE. Constant) + +IF (abool) THEN + CALL e%RaiseWarning(modName//'::'//myName//" - "// & + & "When meshSelection is by MeshID"//CHAR_LF// & + & " and `useFunction` is false, then"//CHAR_LF// & + & " `nodalValueType` in `AbstractBC_`"//CHAR_LF// & + & " object should be Constant.") END IF -END PROCEDURE AbstractBCInitiate +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractBCInitiate()') +#endif +END PROCEDURE bc_Initiate !---------------------------------------------------------------------------- ! diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 index 017a1f00a..2ae68fc55 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 @@ -142,6 +142,24 @@ END PROCEDURE bc_Get +!---------------------------------------------------------------------------- +! bc_GetFEVar +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetFEVar +CHARACTER(*), PARAMETER :: myName = "bc_GetFEVar()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine is under development.') + +! If useFunction is true then +! if constant +! if time +! if space +! if space-time + +! If useFunction is not true then +END PROCEDURE bc_GetFEVar + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -265,7 +283,16 @@ IF (PRESENT(nodalValueType)) nodalValueType = obj%nodalValueType IF (PRESENT(isInitiated)) isInitiated = obj%isInitiated IF (PRESENT(useExternal)) useExternal = obj%useExternal - END PROCEDURE bc_GetQuery +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetPrefix +CHARACTER(*), PARAMETER :: myName = "bc_GetPrefix()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child class.') +END PROCEDURE bc_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 index cf381f35f..12f6c0d24 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 @@ -17,43 +17,49 @@ SUBMODULE(AbstractBC_Class) IOMethods USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! +! Import !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Import CHARACTER(*), PARAMETER :: myName = "bc_Import" TYPE(String) :: dsetname, strval -INTEGER(I4B) :: ierr REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The object is already initiated, deallocate first!') END IF obj%isInitiated = .TRUE. obj%dom => dom -CALL e%raiseInformation(modName//"::"//myName//" - "// & +CALL e%RaiseInformation(modName//"::"//myName//" - "// & & "Importing Boundary condition") IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF IF (.NOT. hdf5%isRead()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have read permission') END IF dsetname = TRIM(group)//"/name" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset name should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -62,7 +68,7 @@ dsetname = TRIM(group)//"/idof" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset idof should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -71,7 +77,7 @@ dsetname = TRIM(group)//"/nodalValueType" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset nodalValueType should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -90,7 +96,7 @@ dsetname = TRIM(group)//"/useFunction" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset useFunction should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -99,7 +105,7 @@ dsetname = TRIM(group)//"/useExternal" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset useExternal should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -108,7 +114,7 @@ dsetname = TRIM(group)//"/Boundary" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset Boundary, which is a group, should be present') ELSE CALL obj%boundary%IMPORT(hdf5=hdf5, group=dsetname%chars()) @@ -117,7 +123,7 @@ IF (.NOT. obj%UseFunction) THEN dsetname = TRIM(group)//"/NodalValue" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset NodalValue should be present') END IF SELECT CASE (obj%nodalValueType) @@ -143,31 +149,30 @@ END PROCEDURE bc_Import !---------------------------------------------------------------------------- -! +! Export !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Export CHARACTER(*), PARAMETER :: myName = "bc_Export" TYPE(String) :: dsetname, strval -INTEGER(I4B) :: ierr REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) IF (.NOT. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The object is not initiated, initiate it first!') END IF -CALL e%raiseInformation(modName//"::"//myName//" - "// & +CALL e%RaiseInformation(modName//"::"//myName//" - "// & & "Exporting Dirichlet Boundary Condition") IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF IF (.NOT. hdf5%isWrite()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have write permission') END IF @@ -214,7 +219,7 @@ IF (.NOT. obj%UseFunction) THEN dsetname = TRIM(group)//"/NodalValue" IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'NodalValue is not allocated, it seems NodalValue is not set') END IF SELECT CASE (obj%nodalValueType) @@ -238,7 +243,7 @@ END PROCEDURE bc_Export !---------------------------------------------------------------------------- -! +! Display !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Display @@ -267,24 +272,24 @@ END SELECT CALL Display("# nodalValueType : "//TRIM(strval%chars()), unitNo=unitNo) -CALL Display(obj%useFunction, "# useFunction : ", unitNo=unitNo) -CALL Display(obj%useExternal, "# useExternal : ", unitNo=unitNo) +CALL Display(obj%useFunction, "useFunction : ", unitNo=unitNo) +CALL Display(obj%useExternal, "useExternal : ", unitNo=unitNo) CALL obj%Boundary%Display(msg="Boundary : ", unitNo=unitNo) IF (.NOT. obj%UseFunction) THEN IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL Display("# NodalValue : NOT ALLOCATED", unitNo=unitNo) + CALL Display("NodalValue : NOT ALLOCATED", unitNo=unitNo) ELSE SELECT CASE (obj%nodalValueType) CASE (Constant) real0 = obj%NodalValue(1, 1) - CALL Display(real0, "# NodalValue : ", unitNo=unitNo) + CALL Display(real0, "NodalValue : ", unitNo=unitNo) CASE (Space, Time) real1 = obj%NodalValue(:, 1) - CALL Display(real1, "# NodalValue : ", unitNo=unitNo, orient="col") + CALL Display(real1, "NodalValue : ", unitNo=unitNo, orient="col") CASE (SpaceTime) real2 = obj%NodalValue(:, :) - CALL Display(real2, "# NodalValue : ", unitNo=unitNo) + CALL Display(real2, "NodalValue : ", unitNo=unitNo) END SELECT END IF END IF @@ -293,6 +298,229 @@ IF (ALLOCATED(real2)) DEALLOCATE (real2) END PROCEDURE bc_Display +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportParamFromToml +CHARACTER(*), PARAMETER :: myName = "bc_ImportParamFromToml()" +INTEGER(I4B) :: origin, stat, nodalValueType, idof +LOGICAL(LGT) :: useFunction, isNormal, isTangent, useExternal +TYPE(String) :: nodalValueType_string, name, astr + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportParamFromToml()') +#endif + +CALL toml_get(table, "useFunction", useFunction, & + & default_useFunction, origin=origin, stat=stat) + +CALL toml_get(table, "isTangent", isTangent, & + & default_isTangent, origin=origin, stat=stat) + +CALL toml_get(table, "isNormal", isNormal, & + & default_isNormal, origin=origin, stat=stat) + +CALL toml_get(table, "useExternal", useExternal, & + & default_useExternal, origin=origin, stat=stat) + +CALL toml_get(table, "nodalValueType", nodalValueType_string%raw, & + & default_nodalValueType_char, origin=origin, stat=stat) + +CALL toml_get(table, "idof", idof, default_idof, origin=origin, stat=stat) + +CALL toml_get(table, "name", name%raw, & + & obj%GetPrefix(), origin=origin, stat=stat) + +astr = nodalValueType_string%Upper() +SELECT CASE (astr%chars()) +CASE ("CONSTANT") + nodalValueType = Constant +CASE ("TIME") + nodalValueType = Time +CASE ("SPACE") + nodalValueType = Space +CASE ("SPACETIME") + nodalValueType = SpaceTime +CASE DEFAULT + nodalValueType = default_nodalValueType +END SELECT +astr = "" + +CALL SetAbstractBCParam( & + & param=param, & + & prefix=obj%GetPrefix(), & + & name=name%chars(), & + & idof=idof, & + & nodalValueType=nodalValueType, & + & useFunction=useFunction, & + & isNormal=isNormal, & + & isTangent=isTangent, & + & useExternal=useExternal & + & ) + +name = "" +nodalValueType_string = "" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "meshSelect_ImportFromToml1()" +TYPE(ParameterList_) :: param +TYPE(toml_table), POINTER :: node +TYPE(MeshSelection_) :: boundary +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: bool1, isFound +REAL(DFP), ALLOCATABLE :: value_r1(:), value_r2(:, :) +REAL(DFP) :: constantValue + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif +CALL param%Initiate() + +CALL obj%ImportParamFromToml(param=param, table=table) + +node => NULL() +CALL toml_get(table, "boundary", node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find [boundary] table in config.') +END IF + +CALL boundary%ImportFromToml(table=node, dom=dom) +CALL obj%Initiate(param=param, boundary=boundary, dom=dom) + +IF (obj%useFunction) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: useFunction = .TRUE., currently you cannot '// & + & 'specify the function.') + RETURN +END IF + +SELECT CASE (obj%nodalValueType) +CASE (Constant) + CALL toml_get(table, "value", constantValue, origin=origin, stat=stat) + IF (stat .NE. toml_stat%success) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: nodalValueType is Constant. So, '// & + & 'value should be a constant (scalar real value).') + RETURN + END IF + CALL obj%Set(constantNodalValue=constantValue) + +CASE (Space, Time) + CALL GetValue(table=table, key="value", VALUE=value_r1, & + & isFound=isFound, origin=origin, stat=stat) + + bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) + + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & + & 'value should be a vector of real numbers.'//CHAR_LF// & + & 'You can specify a vector by directly giving the vector values.'// & + & 'Otherwise, specify filename which contains the vector'// & + & 'values.') + RETURN + END IF + + IF (obj%nodalValueType .EQ. Space) THEN + CALL obj%Set(spaceNodalValue=value_r1) + ELSE + CALL obj%Set(timeNodalValue=value_r1) + END IF + +CASE (SpaceTime) + CALL GetValue(table=table, key="value", VALUE=value_r2, & + & isFound=isFound, origin=origin, stat=stat) + + bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) + + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & + & 'value should be a vector of real numbers.'//CHAR_LF// & + & 'You can specify a vector by directly giving the vector values.'// & + & 'Otherwise, specify filename which contains the vector'// & + & 'values.') + RETURN + END IF + + CALL obj%Set(spaceTimeNodalValue=value_r2) + +END SELECT + +CALL param%DEALLOCATE() +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml()') +#endif +END PROCEDURE bc_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +INTEGER(I4B) :: origin, stat + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +node => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find ['//tomlName//"] table in config.") +END IF + +CALL obj%ImportFromToml(table=node, dom=dom) + +#ifdef DEBUG_VER +IF (PRESENT(printToml)) THEN + CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & + & unitNo=stdout) +END IF +#endif + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml2 + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 index a1cbf4aa5..1890a40b1 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 @@ -26,172 +26,156 @@ MODULE PROCEDURE bc_set CHARACTER(*), PARAMETER :: myName = "bc_set" +LOGICAL(LGT) :: notFunc_notExt, isTimeFunc, isSpaceFunc, isSTFunc, isFunc, & + & isConstVal, isSpaceVal, isSTVal, isTimeVal, bool1, bool2 IF (.NOT. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'AbstractBC_ object is not initiated, initiate it first.') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR ] :: AbstractBC_ object is not initiated.') END IF -IF (.NOT. obj%UseFunction .AND. .NOT. obj%useExternal) THEN - - IF (PRESENT(TimeFunction) .OR. PRESENT(SpaceFunction) & - & .OR. PRESENT(SpaceTimeFunction)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is initiated with useFunction=.FALSE."//CHAR_LF// & - & " and useExternal=.FALSE."//CHAR_LF// & - & "So you cannot provide TimeFunction, SpaceFunction, SpaceTimeFunction") - END IF - - ! constant - - IF (PRESENT(ConstantNodalValue)) THEN - - IF (obj%nodalValueType .NE. Constant) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Constant"// & - & CHAR_LF// & - & 'So, ConstantNodalValue cannot be present') - - ELSE - - CALL Reallocate(obj%NodalValue, 1, 1) - obj%NodalValue = ConstantNodalValue - RETURN - - END IF - - END IF - - ! SpaceNodalValue - - IF (PRESENT(SpaceNodalValue)) THEN - - IF (obj%nodalValueType .NE. Space) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Space"// & - & CHAR_LF// & - & 'So, SpaceNodalValue cannot be present') - - ELSE - - CALL Reallocate(obj%NodalValue, SIZE(SpaceNodalValue), 1) - obj%NodalValue(:, 1) = SpaceNodalValue - RETURN - - END IF - - END IF - - ! TimeNodalValue - - IF (PRESENT(TimeNodalValue)) THEN - - IF (obj%nodalValueType .NE. Time) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Time"// & - & CHAR_LF// & - & 'So, TimeNodalValue cannot be present') - - ELSE - - CALL Reallocate(obj%NodalValue, SIZE(TimeNodalValue), 1) - obj%NodalValue(:, 1) = TimeNodalValue - RETURN - - END IF - - END IF - - ! SpaceTimeNodalValue - - IF (PRESENT(SpaceTimeNodalValue)) THEN - - IF (obj%nodalValueType .NE. SpaceTime) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, SpaceTimeNodalValue cannot be present') - - ELSE - - obj%NodalValue = SpaceTimeNodalValue - RETURN - - END IF - - END IF - -ELSE - - ! SpaceFunction - - IF (PRESENT(SpaceFunction)) THEN - - IF (obj%nodalValueType .NE. Space) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Space"// & - & CHAR_LF// & - & 'So, SpaceFunction cannot be present') - - ELSE - - obj%SpaceFunction => SpaceFunction - RETURN - - END IF - - END IF - - ! TimeNodalValue - - IF (PRESENT(TimeFunction)) THEN - - IF (obj%nodalValueType .NE. Time) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Time"// & - & CHAR_LF// & - & 'So, TimeFunction cannot be present') +notFunc_notExt = (.NOT. obj%useFunction) .AND. & +& (.NOT. obj%useExternal) + +isTimeFunc = PRESENT(timeFunction) +isSpaceFunc = PRESENT(spaceFunction) +isSTFunc = PRESENT(spaceTimeFunction) +isFunc = isSpaceFunc .OR. isTimeFunc .OR. isSTFunc +isConstVal = PRESENT(constantNodalValue) +isSpaceVal = PRESENT(spaceNodalValue) +isTimeVal = PRESENT(timeNodalValue) +isSTVal = PRESENT(spaceTimeNodalValue) + +IF (notFunc_notExt .AND. isFunc) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "//CHAR_LF// & + & "with useFunction=.FALSE. and useExternal=.FALSE."//CHAR_LF// & + & "So you cannot provide timeFunction, spaceFunction, spaceTimeFunction") +END IF - ELSE +bool1 = notFunc_notExt .AND. isConstVal +bool2 = bool1 .AND. obj%nodalValueType .NE. Constant +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Constant "//CHAR_LF// & + & 'So, constantNodalValue cannot be present') + RETURN +END IF - obj%TimeFunction => TimeFunction - RETURN +! constant +IF (bool1) THEN + CALL Reallocate(obj%NodalValue, 1, 1) + obj%NodalValue = constantNodalValue + RETURN +END IF - END IF +! spaceNodalValue +bool1 = notFunc_notExt .AND. isSpaceVal +bool2 = bool1 .AND. (obj%nodalValueType .NE. Space) +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Space"//CHAR_LF// & + & 'So, spaceNodalValue cannot be present.') + RETURN +END IF - END IF +IF (bool1) THEN + CALL Reallocate(obj%NodalValue, SIZE(spaceNodalValue), 1) + obj%NodalValue(:, 1) = spaceNodalValue + RETURN +END IF - ! SpaceTimeNodalValue +! timeNodalValue +bool1 = notFunc_notExt .AND. isTimeVal +bool2 = bool1 .AND. (obj%nodalValueType .NE. Time) +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Time"//CHAR_LF// & + & 'So, timeNodalValue cannot be present.') + RETURN +END IF - IF (PRESENT(SpaceTimeFunction)) THEN +IF (bool1) THEN + CALL Reallocate(obj%NodalValue, SIZE(timeNodalValue), 1) + obj%NodalValue(:, 1) = timeNodalValue + RETURN +END IF - IF (obj%nodalValueType .NE. SpaceTime) THEN +! spaceTimeNodalValue +bool1 = notFunc_notExt .AND. isSTVal +bool2 = bool1 .AND. (obj%nodalValueType .NE. SpaceTime) +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & + & " nodalValueType=SpaceTime"// & + & CHAR_LF// & + & 'So, spaceTimeNodalValue cannot be present') + RETURN +END IF +IF (bool1) THEN + obj%NodalValue = spaceTimeNodalValue + RETURN +END IF - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, SpaceTimeFunction cannot be present') +! spaceFunction +bool1 = isSpaceFunc .AND. (obj%nodalValueType .NE. Space) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Space"// & + & CHAR_LF// & + & 'So, spaceFunction cannot be present') + RETURN +END IF - ELSE +IF (isSpaceFunc) THEN + obj%spaceFunction => spaceFunction + RETURN +END IF - obj%SpaceTimeFunction => SpaceTimeFunction - RETURN +! timeFunction +bool1 = isTimeFunc .AND. (obj%nodalValueType .NE. Time) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & + & "nodalValueType=Time"// & + & CHAR_LF// & + & 'So, timeFunction cannot be present') + RETURN +END IF - END IF +IF (isTimeFunc) THEN + obj%timeFunction => timeFunction + RETURN +END IF - END IF +! spaceTimeFunction +bool1 = isSTFunc .AND. (obj%nodalValueType .NE. SpaceTime) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & + & "nodalValueType=SpaceTime"// & + & CHAR_LF// & + & 'So, spaceTimeFunction cannot be present') + RETURN +END IF - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is initiated with useFunction=TRUE"// & - & CHAR_LF// & - & 'So, SpaceFunction, TimeFunction, or SpaceTimeFunction should be present') +IF (isSTFunc) THEN + obj%spaceTimeFunction => spaceTimeFunction + RETURN +END IF +IF (obj%useFunction .AND. (.NOT. isFunc)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "// & + & "with useFunction=TRUE"// & + & CHAR_LF// & + & 'So, spaceFunction, timeFunction, or spaceTimeFunction '// & + & 'should be present') + RETURN END IF END PROCEDURE bc_set From 19071752623f4935b7fe4e45bf8b4f4eb8ed76f0 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 11:18:28 +0900 Subject: [PATCH 007/117] `DirichletBC_` enhancements Fixes #58 --- .../DirichletBC/src/DirichletBC_Class.F90 | 109 ++++++++++-------- .../DirichletBC_Class@ConstructorMethods.F90 | 48 ++------ .../src/DirichletBC_Class@GetMethods.F90 | 8 ++ .../src/DirichletBC_Class@IOMethods.F90 | 99 ++++++++++++++++ 4 files changed, 175 insertions(+), 89 deletions(-) diff --git a/src/modules/DirichletBC/src/DirichletBC_Class.F90 b/src/modules/DirichletBC/src/DirichletBC_Class.F90 index 4d5f424d7..ad35bf899 100644 --- a/src/modules/DirichletBC/src/DirichletBC_Class.F90 +++ b/src/modules/DirichletBC/src/DirichletBC_Class.F90 @@ -22,6 +22,8 @@ MODULE DirichletBC_Class USE Domain_Class, ONLY: Domain_ USE FPL, ONLY: ParameterList_ USE AbstractBC_Class +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "DirichletBC_Class" @@ -31,6 +33,7 @@ MODULE DirichletBC_Class PUBLIC :: DirichletBCPointer_ PUBLIC :: AddDirichletBC PUBLIC :: GetDirichletBCPointer +PUBLIC :: DirichletBCImportFromToml !---------------------------------------------------------------------------- ! DirichletBC_ @@ -43,9 +46,7 @@ MODULE DirichletBC_Class TYPE, EXTENDS(AbstractBC_) :: DirichletBC_ CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & - & bc_checkEssentialParam - PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix FINAL :: bc_Final END TYPE DirichletBC_ @@ -85,53 +86,6 @@ MODULE SUBROUTINE bc_Deallocate_Ptr_Vector(obj) END SUBROUTINE bc_Deallocate_Ptr_Vector END INTERFACE DEALLOCATE -!---------------------------------------------------------------------------- -! checkEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_checkEssentialParam(obj, param) - CLASS(DirichletBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE bc_checkEssentialParam -END INTERFACE - -!---------------------------------------------------------------------------- -! setDirichletParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE SetDirichletBCParam(param, name, idof, nodalValueType, & - & useFunction, isNormal, isTangent) - TYPE(ParameterList_), INTENT(INOUT) :: param - CHARACTER(*), INTENT(IN) :: name - INTEGER(I4B), INTENT(IN) :: idof - INTEGER(I4B), INTENT(IN) :: nodalValueType - !! Space - !! Time - !! SpaceTime - !! Constant - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTangent - END SUBROUTINE SetDirichletBCParam -END INTERFACE - -PUBLIC :: SetDirichletBCParam - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) - CLASS(DirichletBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(MeshSelection_), INTENT(IN) :: boundary - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -183,6 +137,61 @@ MODULE FUNCTION bc_GetDirichletBCPointer(dbc, dbcNo) RESULT(ans) END FUNCTION bc_GetDirichletBCPointer END INTERFACE GetDirichletBCPointer +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Get the prefix + +INTERFACE + MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) + CLASS(DirichletBC_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bc_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE DirichletBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom, tomlName) + TYPE(DirichletBCPointer_), INTENT(INOUT) :: obj(:) + !! Should be allocated outside + TYPE(toml_table), INTENT(INOUT) :: table + !! Toml table to returned + CLASS(Domain_), TARGET, INTENT(IN) :: dom + !! domain + CHARACTER(*), INTENT(IN) :: tomlName + END SUBROUTINE bc_ImportFromToml1 +END INTERFACE DirichletBCImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE DirichletBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & + & filename, printToml) + TYPE(DirichletBCPointer_), INTENT(INOUT) :: obj(:) + CLASS(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE bc_ImportFromToml2 +END INTERFACE DirichletBCImportFromToml + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 index b37d055f4..8ba7af4f3 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 @@ -19,45 +19,6 @@ IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_checkEssentialParam -CALL AbstractBCcheckEssentialParam(& - & obj=obj, & - & param=param, & - & prefix=myprefix) -END PROCEDURE bc_checkEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE SetDirichletBCParam -CALL SetAbstractBCParam(& - & param=param, & - & prefix=myprefix, & - & name=name, & - & idof=idof, & - & nodalValueType=nodalValueType, & - & useFunction=input(option=useFunction, default=.FALSE.), & - & isNormal=input(option=isNormal, default=.FALSE.), & - & isTangent=input(option=isTangent, default=.FALSE.)) -END PROCEDURE SetDirichletBCParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_Initiate -CALL AbstractBCInitiate(obj=obj, & -& param=param, & -& prefix=myprefix, & -& boundary=boundary, & -& dom=dom) -END PROCEDURE bc_Initiate - !---------------------------------------------------------------------------- ! Final !---------------------------------------------------------------------------- @@ -104,6 +65,11 @@ MODULE PROCEDURE bc_AddDirichletBC CHARACTER(*), PARAMETER :: myName = "bc_AddDirichletBC" +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AddDirichletBC()') +#endif + IF (dbcNo .GT. SIZE(dbc)) THEN CALL e%raiseError(modName//'::'//myName//" - "// & & '[OUT OF BOUND ERROR] :: dbcNo [= '//TOSTRING(dbcNo)// & @@ -124,6 +90,10 @@ & boundary=boundary, & & dom=dom) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AddDirichletBC()') +#endif END PROCEDURE bc_AddDirichletBC END SUBMODULE ConstructorMethods diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 index a5e2676b3..cbb5196f6 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 @@ -42,4 +42,12 @@ END PROCEDURE bc_GetDirichletBCPointer +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetPrefix + ans = myprefix +END PROCEDURE bc_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 index 19e6ac5e2..68c12fa03 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 @@ -16,6 +16,105 @@ ! SUBMODULE(DirichletBC_Class) IOMethods +USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml1()" +TYPE(toml_table), POINTER :: node +TYPE(toml_array), POINTER :: array +INTEGER(I4B) :: origin, stat, tsize, ii, tsize1 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +tsize1 = SIZE(obj) + +array => NULL() +CALL toml_get(table, tomlName, array, origin=origin, & + & requested=.FALSE., stat=stat) + +IF (.NOT. ASSOCIATED(array)) THEN + IF (tsize1 .GT. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + ELSE + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + END IF + RETURN +END IF + +tsize = toml_len(array) +IF (tsize .NE. tsize1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The number of boundary condition '// char_lf// & + & ' in the toml config ('//tostring(tsize)//') is not same '// & + & ' as the size of obj ('//tostring(tsize1)//")") + RETURN +END IF + +DO ii = 1, tsize + node => NULL() + CALL toml_get(array, ii, node) + IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: DirichletBC '//tostring(ii)// & + & ' cannot be read from the toml file.') + END IF + IF (.NOT. ASSOCIATED(obj(ii)%ptr)) ALLOCATE (obj(ii)%ptr) + CALL obj(ii)%ptr%ImportFromToml(table=node, dom=dom) +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +CALL DirichletBCImportFromToml(obj=obj, table=table, dom=dom, & + & tomlName=tomlName) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml2 END SUBMODULE IOMethods From 6cd03a884df4c048fbe5a1645bfee07eb336f8a0 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 11:30:34 +0900 Subject: [PATCH 008/117] Hash-table support in easifem Fixes #173 --- src/modules/Fhash/CMakeLists.txt | 19 + src/modules/Fhash/src/fhash.F90 | 14 + .../Fhash/src/fhash_data_container.F90 | 241 ++++++++ src/modules/Fhash/src/fhash_fnv.F90 | 181 ++++++ src/modules/Fhash/src/fhash_key/base.F90 | 42 ++ src/modules/Fhash/src/fhash_key/char.F90 | 76 +++ src/modules/Fhash/src/fhash_key/int32.F90 | 76 +++ src/modules/Fhash/src/fhash_key/int32_1d.F90 | 82 +++ src/modules/Fhash/src/fhash_key/int64.F90 | 76 +++ src/modules/Fhash/src/fhash_key/int64_1d.F90 | 82 +++ src/modules/Fhash/src/fhash_sll.F90 | 277 +++++++++ src/modules/Fhash/src/fhash_tbl.F90 | 571 ++++++++++++++++++ src/modules/Fhash/src/fhash_tbl_iter.F90 | 83 +++ 13 files changed, 1820 insertions(+) create mode 100644 src/modules/Fhash/CMakeLists.txt create mode 100644 src/modules/Fhash/src/fhash.F90 create mode 100644 src/modules/Fhash/src/fhash_data_container.F90 create mode 100644 src/modules/Fhash/src/fhash_fnv.F90 create mode 100644 src/modules/Fhash/src/fhash_key/base.F90 create mode 100644 src/modules/Fhash/src/fhash_key/char.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int32.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int32_1d.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int64.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int64_1d.F90 create mode 100644 src/modules/Fhash/src/fhash_sll.F90 create mode 100644 src/modules/Fhash/src/fhash_tbl.F90 create mode 100644 src/modules/Fhash/src/fhash_tbl_iter.F90 diff --git a/src/modules/Fhash/CMakeLists.txt b/src/modules/Fhash/CMakeLists.txt new file mode 100644 index 000000000..26f0a3426 --- /dev/null +++ b/src/modules/Fhash/CMakeLists.txt @@ -0,0 +1,19 @@ +# This program is taken from +# https://github.com/LKedward/fhash + +SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +TARGET_SOURCES( + ${PROJECT_NAME} PRIVATE + ${src_path}/fhash.F90 + ${src_path}/fhash_sll.F90 + ${src_path}/fhash_data_container.F90 + ${src_path}/fhash_tbl.F90 + ${src_path}/fhash_tbl_iter.F90 + ${src_path}/fhash_fnv.F90 + ${src_path}/fhash_key/base.F90 + ${src_path}/fhash_key/int32.F90 + ${src_path}/fhash_key/int64.F90 + ${src_path}/fhash_key/char.F90 + ${src_path}/fhash_key/int32_1d.F90 + ${src_path}/fhash_key/int64_1d.F90 +) diff --git a/src/modules/Fhash/src/fhash.F90 b/src/modules/Fhash/src/fhash.F90 new file mode 100644 index 000000000..20092465a --- /dev/null +++ b/src/modules/Fhash/src/fhash.F90 @@ -0,0 +1,14 @@ +! fhash module is taken from +! https://github.com/LKedward/fhash + +MODULE fhash +USE fhash_tbl, ONLY: fhash_tbl_t +USE fhash_tbl_iter, ONLY: fhash_iter_t +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_key_char, ONLY: fhash_key_char_t, fhash_key +USE fhash_key_int32, ONLY: fhash_key_int32_t, fhash_key +USE fhash_key_int64, ONLY: fhash_key_int64_t, fhash_key +USE fhash_key_int32_1d, ONLY: fhash_key_int32_1d_t, fhash_key +USE fhash_key_int64_1d, ONLY: fhash_key_int64_1d_t, fhash_key +IMPLICIT NONE +END MODULE fhash diff --git a/src/modules/Fhash/src/fhash_data_container.F90 b/src/modules/Fhash/src/fhash_data_container.F90 new file mode 100644 index 000000000..41fdaac69 --- /dev/null +++ b/src/modules/Fhash/src/fhash_data_container.F90 @@ -0,0 +1,241 @@ +! This library is taken from +! https://github.com/LKedward/fhash +!> Implements simple container type +!> for polymorphic scalars and 1D arrays +MODULE fhash_data_container +USE ISO_FORTRAN_ENV, ONLY: sp => REAL32, dp => REAL64, INT32, INT64 +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_container_t +PUBLIC fhash_container + +!> Generic container for scalar and 1D data +TYPE fhash_container_t + + CLASS(*), ALLOCATABLE :: scalar_data + CLASS(*), POINTER :: scalar_ptr => NULL() + +CONTAINS + + PROCEDURE :: allocated => fhash_container_allocated + PROCEDURE :: get => fhash_container_get_scalar + PROCEDURE :: get_ptr => fhash_container_get_scalar_ptr + +END TYPE fhash_container_t + +!> Create a fhash_container object from a polymorphic value +INTERFACE fhash_container + MODULE PROCEDURE fhash_container_scalar +END INTERFACE fhash_container + +CONTAINS + +!> Helper to initialise a polymorphic data container with scalar +FUNCTION fhash_container_scalar(VALUE, POINTER) RESULT(container) + + !> Value to store + CLASS(*), INTENT(in), TARGET :: VALUE + + !> If .true., store pointer to value instead of copying + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + TYPE(fhash_container_t) :: container + + IF (PRESENT(POINTER)) THEN + IF (POINTER) THEN + container%scalar_ptr => VALUE + ELSE + IF (ALLOCATED(container%scalar_data)) DEALLOCATE (container%scalar_data) + ALLOCATE (container%scalar_data, source=VALUE) + END IF + ELSE + IF (ALLOCATED(container%scalar_data)) DEALLOCATE (container%scalar_data) + ALLOCATE (container%scalar_data, source=VALUE) + END IF + +END FUNCTION fhash_container_scalar + +!> Helper to determine if container contains anything +FUNCTION fhash_container_allocated(container) RESULT(alloc) + CLASS(fhash_container_t), INTENT(in) :: container + LOGICAL :: alloc + + alloc = ALLOCATED(container%scalar_data) .OR. & + ASSOCIATED(container%scalar_ptr) + +END FUNCTION fhash_container_allocated + +!> Helper to return container value as intrinsic type + subroutine fhash_container_get_scalar(container,i32,i64,r32,r64,char,bool,raw,match,type_string) + CLASS(fhash_container_t), INTENT(in), TARGET :: container + INTEGER(INT32), INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), INTENT(out), OPTIONAL :: i64 + REAL(sp), INTENT(out), OPTIONAL :: r32 + REAL(dp), INTENT(out), OPTIONAL :: r64 + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: char + LOGICAL, INTENT(out), OPTIONAL :: bool + CLASS(*), ALLOCATABLE, INTENT(out), OPTIONAL :: raw + LOGICAL, INTENT(out), OPTIONAL :: match + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: type_string + + CLASS(*), POINTER :: DATA + + IF (PRESENT(match)) match = .FALSE. + + IF (.NOT. container%ALLOCATED()) RETURN + + IF (ALLOCATED(container%scalar_data)) THEN + DATA => container%scalar_data + ELSE + DATA => container%scalar_ptr + END IF + + IF (PRESENT(raw)) THEN + IF (PRESENT(match)) match = .TRUE. + ALLOCATE (raw, source=DATA) + END IF + + SELECT TYPE (d => DATA) + TYPE is (INTEGER(INT32)) + IF (PRESENT(type_string)) type_string = 'integer32' + IF (PRESENT(i32)) THEN + IF (PRESENT(match)) match = .TRUE. + i32 = d + RETURN + END IF + + TYPE is (INTEGER(INT64)) + IF (PRESENT(type_string)) type_string = 'integer64' + IF (PRESENT(i64)) THEN + IF (PRESENT(match)) match = .TRUE. + i64 = d + RETURN + END IF + + TYPE is (REAL(sp)) + IF (PRESENT(type_string)) type_string = 'real32' + IF (PRESENT(r32)) THEN + IF (PRESENT(match)) match = .TRUE. + r32 = d + RETURN + END IF + + TYPE is (REAL(dp)) + IF (PRESENT(type_string)) type_string = 'real64' + IF (PRESENT(r64)) THEN + IF (PRESENT(match)) match = .TRUE. + r64 = d + RETURN + END IF + + TYPE is (CHARACTER(*)) + IF (PRESENT(type_string)) type_string = 'character*' + IF (PRESENT(char)) THEN + IF (PRESENT(match)) match = .TRUE. + char = d + RETURN + END IF + + TYPE is (LOGICAL) + IF (PRESENT(type_string)) type_string = 'logical' + IF (PRESENT(bool)) THEN + IF (PRESENT(match)) match = .TRUE. + bool = d + RETURN + END IF + + CLASS default + IF (PRESENT(type_string)) type_string = 'unknown' + + END SELECT + +END SUBROUTINE fhash_container_get_scalar + +!> Helper to return pointer to container value as intrinsic type + subroutine fhash_container_get_scalar_ptr(container,i32,i64,r32,r64,char,bool,raw,match,type_string) + CLASS(fhash_container_t), INTENT(in), TARGET :: container + INTEGER(INT32), POINTER, INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), POINTER, INTENT(out), OPTIONAL :: i64 + REAL(sp), POINTER, INTENT(out), OPTIONAL :: r32 + REAL(dp), POINTER, INTENT(out), OPTIONAL :: r64 + CHARACTER(:), POINTER, INTENT(out), OPTIONAL :: char + LOGICAL, POINTER, INTENT(out), OPTIONAL :: bool + CLASS(*), POINTER, INTENT(out), OPTIONAL :: raw + LOGICAL, INTENT(out), OPTIONAL :: match + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: type_string + + CLASS(*), POINTER :: DATA + + IF (PRESENT(match)) match = .FALSE. + + IF (.NOT. container%ALLOCATED()) RETURN + + IF (ALLOCATED(container%scalar_data)) THEN + DATA => container%scalar_data + ELSE + DATA => container%scalar_ptr + END IF + + IF (PRESENT(raw)) THEN + IF (PRESENT(match)) match = .TRUE. + raw => DATA + END IF + + SELECT TYPE (d => DATA) + TYPE is (INTEGER(INT32)) + IF (PRESENT(i32)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'integer32' + i32 => d + RETURN + END IF + + TYPE is (INTEGER(INT64)) + IF (PRESENT(i64)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'integer64' + i64 => d + RETURN + END IF + + TYPE is (REAL(sp)) + IF (PRESENT(r32)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'real32' + r32 => d + RETURN + END IF + + TYPE is (REAL(dp)) + IF (PRESENT(r64)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'real64' + r64 => d + RETURN + END IF + + TYPE is (CHARACTER(*)) + IF (PRESENT(char)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'character*' + char => d + RETURN + END IF + + TYPE is (LOGICAL) + IF (PRESENT(bool)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'logical' + bool => d + RETURN + END IF + + CLASS DEFAULT + IF (PRESENT(type_string)) type_string = 'unknown' + + END SELECT + +END SUBROUTINE fhash_container_get_scalar_ptr + +END MODULE fhash_data_container diff --git a/src/modules/Fhash/src/fhash_fnv.F90 b/src/modules/Fhash/src/fhash_fnv.F90 new file mode 100644 index 000000000..1bd04b5b7 --- /dev/null +++ b/src/modules/Fhash/src/fhash_fnv.F90 @@ -0,0 +1,181 @@ +!> A module for Fowler–Noll–Vo (FNV) hashing +!> +!> Implements the FNV 1a algorithm for 32bit hashes +!> +!> Supports hashing of: +!> - 32bit integers (scalar & 1D array) +!> - 64bit integers (scalar & 1D array) +!> - character(*), default kind +!> +!> The lack of unsigned arithmetic in Fortran means that +!> 64bit arithmetic is needed to perform 32bit hashing. +!> Hashes are therefore returned as int64. +!> +MODULE fhash_fnv +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE ISO_C_BINDING, ONLY: C_CHAR +IMPLICIT NONE + +PRIVATE +PUBLIC :: fnv_1a, hash_string + +!> Starting seed +INTEGER(INT64), PARAMETER :: FNV_OFFSET_32 = 2166136261_INT64 + +!> Hashing prime +INTEGER(INT64), PARAMETER :: FNV_PRIME_32 = 16777619_INT64 + +!> Generic interface to perform hashing +!> +!> Usage: +!>```fortran +!> fnv_1a([seed],input) +!>``` +!> where `input` is any of the supported types +INTERFACE fnv_1a + MODULE PROCEDURE fnv_1a_char_scalar + MODULE PROCEDURE fnv_1a_char_scalar_seed + MODULE PROCEDURE fnv_1a_int32_scalar + MODULE PROCEDURE fnv_1a_int32_scalar_seed + MODULE PROCEDURE fnv_1a_int32_1d + MODULE PROCEDURE fnv_1a_int32_1d_seed + MODULE PROCEDURE fnv_1a_int64_scalar + MODULE PROCEDURE fnv_1a_int64_scalar_seed + MODULE PROCEDURE fnv_1a_int64_1d + MODULE PROCEDURE fnv_1a_int64_1d_seed +END INTERFACE fnv_1a + +CONTAINS + +!> Hash a single default kind character variable +PURE FUNCTION fnv_1a_char_scalar(input) RESULT(hash) + CHARACTER(*), INTENT(in) :: input + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_char_scalar + +!> Hash a character(*) string of default kind +PURE FUNCTION fnv_1a_char_scalar_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + CHARACTER(*), INTENT(in) :: input + INTEGER(INT64) :: hash + + INTEGER :: i + INTEGER(INT64) :: item + + hash = seed + + DO i = 1, LEN(input) + item = TRANSFER([IACHAR(input(i:i), INT32), 0_INT32], item) + hash = IEOR(hash, item) * fnv_prime_32 + END DO + +END FUNCTION fnv_1a_char_scalar_seed + +!> Hash a single 32bit integer +PURE FUNCTION fnv_1a_int32_scalar(input) RESULT(hash) + INTEGER(INT32), INTENT(in) :: input + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int32_scalar + +!> Hash a single 32bit integer with a starting seed +PURE FUNCTION fnv_1a_int32_scalar_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT32), INTENT(in) :: input + INTEGER(INT64) :: hash + + CHARACTER(len=4, kind=C_CHAR) :: chars + + chars = TRANSFER(input, chars) + + hash = fnv_1a(seed, chars) + +END FUNCTION fnv_1a_int32_scalar_seed + +!> Hash a 1D array of 32bit integers +PURE FUNCTION fnv_1a_int32_1d(input) RESULT(hash) + INTEGER(INT32), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int32_1d + +!> Hash a 1D array of 32bit integers with a starting seed +PURE FUNCTION fnv_1a_int32_1d_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT32), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + INTEGER :: i + + hash = seed + DO i = 1, SIZE(input) + hash = fnv_1a(hash, input(i)) + END DO + +END FUNCTION fnv_1a_int32_1d_seed + +!> Hash a single 64bit integer +PURE FUNCTION fnv_1a_int64_scalar(input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: input + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int64_scalar + +!> Hash a single 64bit integer with a starting seed +PURE FUNCTION fnv_1a_int64_scalar_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT64), INTENT(in) :: input + INTEGER(INT64) :: hash + + CHARACTER(len=8, kind=C_CHAR) :: chars + + chars = TRANSFER(input, chars) + + hash = fnv_1a(seed, chars) + +END FUNCTION fnv_1a_int64_scalar_seed + +!> Hash a 1D array of 64bit integers +PURE FUNCTION fnv_1a_int64_1d(input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int64_1d + +!> Hash a 1D array of 64bit integers with a starting seed +PURE FUNCTION fnv_1a_int64_1d_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT64), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + INTEGER :: i + + hash = seed + DO i = 1, SIZE(input) + hash = fnv_1a(hash, input(i)) + END DO + +END FUNCTION fnv_1a_int64_1d_seed + +!> Help fcn to convert hash to hex representation +FUNCTION hash_string(hash_value) RESULT(str) + INTEGER(INT64), INTENT(in) :: hash_value + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(len=10) :: str) + WRITE (str, '(Z0)') INT(hash_value, INT32) + +END FUNCTION hash_string + +END MODULE fhash_fnv diff --git a/src/modules/Fhash/src/fhash_key/base.F90 b/src/modules/Fhash/src/fhash_key/base.F90 new file mode 100644 index 000000000..e7537bdec --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/base.F90 @@ -0,0 +1,42 @@ +!> Implements an abstract type for hash keys +!> +MODULE fhash_key_base +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_t + +!> Abstract base type for defining hash keys +TYPE, ABSTRACT :: fhash_key_t +CONTAINS + PROCEDURE(hash_proc), DEFERRED :: hash + PROCEDURE(equality_proc), DEFERRED :: equals + PROCEDURE(to_string_proc), DEFERRED :: to_string + GENERIC, PUBLIC :: OPERATOR(==) => equals +END TYPE fhash_key_t + +ABSTRACT INTERFACE + + PURE FUNCTION equality_proc(key1, key2) RESULT(keys_equal) + IMPORT + CLASS(fhash_key_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + END FUNCTION equality_proc + + PURE FUNCTION hash_proc(key) RESULT(hash) + IMPORT + CLASS(fhash_key_t), INTENT(in) :: key + INTEGER(INT64) :: hash + END FUNCTION hash_proc + + FUNCTION to_string_proc(key) RESULT(str) + IMPORT + CLASS(fhash_key_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + END FUNCTION to_string_proc + +END INTERFACE + +END MODULE fhash_key_base diff --git a/src/modules/Fhash/src/fhash_key/char.F90 b/src/modules/Fhash/src/fhash_key/char.F90 new file mode 100644 index 000000000..63f1a90e9 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/char.F90 @@ -0,0 +1,76 @@ +!> Implements a concrete type for scalar int32 hash keys +!> +MODULE fhash_key_char +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_char_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_char_t + PRIVATE + CHARACTER(:), ALLOCATABLE :: VALUE +CONTAINS + PROCEDURE, PASS :: hash => key_hash_char + PROCEDURE, PASS :: equals => key_equal_char + PROCEDURE, PASS :: to_string => key_char_to_string +END TYPE fhash_key_char_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_char +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_char(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_char_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_char_t) + IF (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE)) THEN + IF (key1%VALUE == k2%VALUE) THEN + keys_equal = .TRUE. + RETURN + END IF + END IF + END SELECT + +END FUNCTION key_equal_char + +!> Generate hash of key +PURE FUNCTION key_hash_char(key) RESULT(hash) + CLASS(fhash_key_char_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_char + +!> Generate string representation of hash +FUNCTION key_char_to_string(key) RESULT(str) + CLASS(fhash_key_char_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + str = key%VALUE + +END FUNCTION key_char_to_string + +!> Create new key container from a scalar int32 +FUNCTION key_from_char(source) RESULT(key) + CHARACTER(*), INTENT(in) :: source + TYPE(fhash_key_char_t) :: key + + key%VALUE = source + +END FUNCTION key_from_char + +END MODULE fhash_key_char diff --git a/src/modules/Fhash/src/fhash_key/int32.F90 b/src/modules/Fhash/src/fhash_key/int32.F90 new file mode 100644 index 000000000..0d3fac8e2 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int32.F90 @@ -0,0 +1,76 @@ +!> Implements a concrete type for scalar int32 hash keys +!> +MODULE fhash_key_int32 +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int32_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int32_t + PRIVATE + INTEGER(INT32) :: VALUE +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int32 + PROCEDURE, PASS :: equals => key_equal_int32 + PROCEDURE, PASS :: to_string => key_int32_to_string +END TYPE fhash_key_int32_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int32 +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int32(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int32_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int32_t) + IF (key1%VALUE == k2%VALUE) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int32 + +!> Generate hash of key +PURE FUNCTION key_hash_int32(key) RESULT(hash) + CLASS(fhash_key_int32_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int32 + +!> Generate string representation of hash +PURE FUNCTION key_int32_to_string(key) RESULT(str) + CLASS(fhash_key_int32_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int32_to_string + +!> Create new key container from a scalar int32 +FUNCTION key_from_int32(source) RESULT(key) + INTEGER(INT32), INTENT(in) :: source + TYPE(fhash_key_int32_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int32 + +END MODULE fhash_key_int32 diff --git a/src/modules/Fhash/src/fhash_key/int32_1d.F90 b/src/modules/Fhash/src/fhash_key/int32_1d.F90 new file mode 100644 index 000000000..78c0123e5 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int32_1d.F90 @@ -0,0 +1,82 @@ +!> Implements a concrete type for 1D int32 array hash keys +!> +MODULE fhash_key_int32_1d +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int32_1d_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int32_1d_t + PRIVATE + INTEGER(INT32), ALLOCATABLE :: VALUE(:) +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int32_1d + PROCEDURE, PASS :: equals => key_equal_int32_1d + PROCEDURE, PASS :: to_string => key_int32_1d_to_string +END TYPE fhash_key_int32_1d_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int32_1d +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int32_1d(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int32_1d_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int32_1d_t) + IF (.NOT. (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE))) THEN + RETURN + END IF + IF (SIZE(key1%VALUE) /= SIZE(k2%VALUE)) THEN + RETURN + END IF + IF (ALL(key1%VALUE == k2%VALUE)) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int32_1d + +!> Generate hash of key +PURE FUNCTION key_hash_int32_1d(key) RESULT(hash) + CLASS(fhash_key_int32_1d_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int32_1d + +!> Generate string representation of hash +PURE FUNCTION key_int32_1d_to_string(key) RESULT(str) + CLASS(fhash_key_int32_1d_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int32_1d_to_string + +!> Create new key container from a scalar int32 +FUNCTION key_from_int32_1d(source) RESULT(key) + INTEGER(INT32), INTENT(in) :: source(:) + TYPE(fhash_key_int32_1d_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int32_1d + +END MODULE fhash_key_int32_1d diff --git a/src/modules/Fhash/src/fhash_key/int64.F90 b/src/modules/Fhash/src/fhash_key/int64.F90 new file mode 100644 index 000000000..a4b5e18d2 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int64.F90 @@ -0,0 +1,76 @@ +!> Implements a concrete type for scalar int64 hash keys +!> +MODULE fhash_key_int64 +USE ISO_FORTRAN_ENV, ONLY: INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int64_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int64_t + PRIVATE + INTEGER(INT64) :: VALUE +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int64 + PROCEDURE, PASS :: equals => key_equal_int64 + PROCEDURE, PASS :: to_string => key_int64_to_string +END TYPE fhash_key_int64_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int64 +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int64(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int64_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int64_t) + IF (key1%VALUE == k2%VALUE) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int64 + +!> Generate hash of key +PURE FUNCTION key_hash_int64(key) RESULT(hash) + CLASS(fhash_key_int64_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int64 + +!> Generate string representation of hash +PURE FUNCTION key_int64_to_string(key) RESULT(str) + CLASS(fhash_key_int64_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int64_to_string + +!> Create new key container from a scalar int64 +FUNCTION key_from_int64(source) RESULT(key) + INTEGER(INT64), INTENT(in) :: source + TYPE(fhash_key_int64_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int64 + +END MODULE fhash_key_int64 diff --git a/src/modules/Fhash/src/fhash_key/int64_1d.F90 b/src/modules/Fhash/src/fhash_key/int64_1d.F90 new file mode 100644 index 000000000..2c2c2ccd8 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int64_1d.F90 @@ -0,0 +1,82 @@ +!> Implements a concrete type for 1D int64 array hash keys +!> +MODULE fhash_key_int64_1d +USE ISO_FORTRAN_ENV, ONLY: INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int64_1d_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int64_1d_t + PRIVATE + INTEGER(INT64), ALLOCATABLE :: VALUE(:) +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int64_1d + PROCEDURE, PASS :: equals => key_equal_int64_1d + PROCEDURE, PASS :: to_string => key_int64_1d_to_string +END TYPE fhash_key_int64_1d_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int64_1d +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int64_1d(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int64_1d_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int64_1d_t) + IF (.NOT. (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE))) THEN + RETURN + END IF + IF (SIZE(key1%VALUE) /= SIZE(k2%VALUE)) THEN + RETURN + END IF + IF (ALL(key1%VALUE == k2%VALUE)) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int64_1d + +!> Generate hash of key +PURE FUNCTION key_hash_int64_1d(key) RESULT(hash) + CLASS(fhash_key_int64_1d_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int64_1d + +!> Generate string representation of hash +PURE FUNCTION key_int64_1d_to_string(key) RESULT(str) + CLASS(fhash_key_int64_1d_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int64_1d_to_string + +!> Create new key container from a scalar int64 +FUNCTION key_from_int64_1d(source) RESULT(key) + INTEGER(INT64), INTENT(in) :: source(:) + TYPE(fhash_key_int64_1d_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int64_1d + +END MODULE fhash_key_int64_1d diff --git a/src/modules/Fhash/src/fhash_sll.F90 b/src/modules/Fhash/src/fhash_sll.F90 new file mode 100644 index 000000000..c9aec1190 --- /dev/null +++ b/src/modules/Fhash/src/fhash_sll.F90 @@ -0,0 +1,277 @@ +!> Implements singly-linked list (sll) node with generic data container +!> +MODULE fhash_sll +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_data_container, ONLY: fhash_container_t +IMPLICIT NONE + +!> Node type for hash table singly linked list +TYPE fhash_node_t + + CLASS(fhash_key_t), ALLOCATABLE :: key + TYPE(fhash_container_t) :: VALUE + TYPE(fhash_node_t), POINTER :: next => NULL() + +END TYPE fhash_node_t + +CONTAINS + +!> Append node to SLL +RECURSIVE SUBROUTINE sll_push_node(node, key, VALUE, POINTER) + + !> Node to which to add data + TYPE(fhash_node_t), INTENT(inout) :: node + + !> Key to add + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value to add + CLASS(*), INTENT(in), TARGET :: VALUE + + !> Store only a point if .true. + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + IF (ALLOCATED(node%key)) THEN + + IF (node%key == key) THEN + + CALL sll_node_set(node, VALUE, POINTER) + RETURN + + END IF + + IF (.NOT. ASSOCIATED(node%next)) THEN + ALLOCATE (node%next) + END IF + + CALL sll_push_node(node%next, key, VALUE, POINTER) + + ELSE + + node%key = key + CALL sll_node_set(node, VALUE, POINTER) + + END IF + +END SUBROUTINE sll_push_node + +!> Set container value in node +!> +SUBROUTINE sll_node_set(node, VALUE, POINTER) + + !> Node to which to add data + TYPE(fhash_node_t), INTENT(inout) :: node + + !> Value to set + CLASS(*), INTENT(in), TARGET :: VALUE + + !> Store only a pointer if .true. + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + IF (PRESENT(POINTER)) THEN + IF (POINTER) THEN + node%VALUE%scalar_ptr => VALUE + RETURN + END IF + END IF + + IF (ALLOCATED(node%VALUE%scalar_data)) DEALLOCATE (node%VALUE%scalar_data) + ALLOCATE (node%VALUE%scalar_data, source=VALUE) + +END SUBROUTINE sll_node_set + +!> Search for a node with a specific key. +!> Returns a pointer to the 'data' component of the corresponding node. +!> Pointer is not associated if node cannot be found +RECURSIVE SUBROUTINE sll_find_in(node, key, DATA, found) + + !> Node to search in + TYPE(fhash_node_t), INTENT(in), TARGET :: node + + !> Key to look for + CLASS(fhash_key_t) :: key + + !> Pointer to value container if found. + !> (Unassociated if the key is not found in node) + TYPE(fhash_container_t), POINTER, INTENT(out) :: DATA + + LOGICAL, INTENT(out), OPTIONAL :: found + + DATA => NULL() + + IF (PRESENT(found)) found = .FALSE. + + IF (.NOT. ALLOCATED(node%key)) THEN + + RETURN + + ELSE IF (node%key == key) THEN + + IF (PRESENT(found)) found = .TRUE. + DATA => node%VALUE + RETURN + + ELSE IF (ASSOCIATED(node%next)) THEN + + CALL sll_find_in(node%next, key, DATA, found) + + END IF + +END SUBROUTINE sll_find_in + +!> Return a node at a specific depth in the sll +RECURSIVE SUBROUTINE sll_get_at(node, depth, key, DATA, found) + + !> Node to search in + TYPE(fhash_node_t), INTENT(in), TARGET :: node + + !> Node depth to access + INTEGER, INTENT(in) :: depth + + !> Key of found item + !> (Unallocated if no node is found at specified depth) + CLASS(fhash_key_t), INTENT(out), ALLOCATABLE :: key + + !> Pointer to value container if found. + !> (Unassociated if no node is found at specified depth) + TYPE(fhash_container_t), POINTER, INTENT(out) :: DATA + + LOGICAL, INTENT(out), OPTIONAL :: found + + DATA => NULL() + + IF (PRESENT(found)) found = .FALSE. + + IF (.NOT. ALLOCATED(node%key)) THEN + + RETURN + + ELSE IF (depth == 1) THEN + + IF (PRESENT(found)) found = .TRUE. + key = node%key + DATA => node%VALUE + RETURN + + ELSE IF (ASSOCIATED(node%next)) THEN + + CALL sll_get_at(node%next, depth - 1, key, DATA, found) + + END IF + +END SUBROUTINE sll_get_at + +!> Search for a node with a specific key and remove +RECURSIVE SUBROUTINE sll_remove(node, key, found, parent_node) + + !> Node to remove from + TYPE(fhash_node_t), INTENT(inout) :: node + + !> Key to remove + CLASS(fhash_key_t) :: key + + !> Indicates if the key was found in node and removed + LOGICAL, OPTIONAL, INTENT(out) :: found + + !> Used internally + TYPE(fhash_node_t), INTENT(inout), OPTIONAL :: parent_node + + TYPE(fhash_node_t), POINTER :: next_temp + + IF (PRESENT(found)) THEN + found = .FALSE. + END IF + + IF (.NOT. ALLOCATED(node%key)) THEN + + RETURN + + ELSE IF (node%key == key) THEN + + IF (PRESENT(found)) THEN + found = .TRUE. + END IF + + IF (.NOT. PRESENT(parent_node)) THEN + ! This is the top-level node + IF (ASSOCIATED(node%next)) THEN + ! Replace with next + next_temp => node%next + node = next_temp + DEALLOCATE (next_temp) + RETURN + ELSE + ! No children, just deallocate + DEALLOCATE (node%key) + RETURN + END IF + + ELSE + ! Not top-level node + IF (ASSOCIATED(node%next)) THEN + ! Join previous with next + next_temp => node%next + DEALLOCATE (parent_node%next) + parent_node%next => next_temp + RETURN + ELSE + ! No children, just deallocate + DEALLOCATE (node%key) + DEALLOCATE (parent_node%next) + RETURN + END IF + END IF + + ELSE IF (ASSOCIATED(node%next)) THEN + ! Look further down + CALL sll_remove(node%next, key, found, node) + + END IF + +END SUBROUTINE sll_remove + +!> Deallocate node components and those of its children +RECURSIVE SUBROUTINE sll_clean(node) + + !> Node to search in + TYPE(fhash_node_t), INTENT(inout) :: node + + IF (ASSOCIATED(node%next)) THEN + + CALL sll_clean(node%next) + DEALLOCATE (node%next) + + END IF + +END SUBROUTINE sll_clean + +!> Determine depth of SLL +FUNCTION node_depth(node) RESULT(depth) + + !> Node to check depth + TYPE(fhash_node_t), INTENT(in), TARGET :: node + + INTEGER :: depth + + TYPE(fhash_node_t), POINTER :: current + + IF (.NOT. ALLOCATED(node%key)) THEN + + depth = 0 + RETURN + + ELSE + + depth = 1 + current => node + DO WHILE (ASSOCIATED(current%next)) + depth = depth + 1 + current => current%next + END DO + + END IF + +END FUNCTION node_depth + +END MODULE fhash_sll diff --git a/src/modules/Fhash/src/fhash_tbl.F90 b/src/modules/Fhash/src/fhash_tbl.F90 new file mode 100644 index 000000000..a56527ac8 --- /dev/null +++ b/src/modules/Fhash/src/fhash_tbl.F90 @@ -0,0 +1,571 @@ +MODULE fhash_tbl +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64, sp => REAL32, dp => REAL64 +USE fhash_data_container, ONLY: fhash_container +USE fhash_sll +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_tbl_t + +!> This condition should be unreachable by the public interface +INTEGER, PARAMETER, PUBLIC :: FHASH_INTERNAL_ERROR = -4 + +!> Error flag for operating on an unallocated table +INTEGER, PARAMETER, PUBLIC :: FHASH_EMPTY_TABLE = -3 + +!> Error flag for when retrieved data-type does not +!> match that expected by the invoked getter function +!> (`get_int32`,`get_int63`,`get_float`,'get_double`,`get_char`) +INTEGER, PARAMETER, PUBLIC :: FHASH_FOUND_WRONG_TYPE = -2 + +!> Error flag for when specified key is not found in the hash table +INTEGER, PARAMETER, PUBLIC :: FHASH_KEY_NOT_FOUND = -1 + +!> Default allocation size +INTEGER, PARAMETER :: FHASH_DEFAULT_ALLOCATION = 127 + +TYPE fhash_tbl_t + + TYPE(fhash_node_t), ALLOCATABLE :: buckets(:) + +CONTAINS + + PROCEDURE :: ALLOCATE => fhash_tbl_allocate + PROCEDURE :: unset => fhash_tbl_unset + PROCEDURE :: check_key => fhash_tbl_check_key + PROCEDURE :: stats => fhash_tbl_stats + + PROCEDURE :: fhash_tbl_set_scalar + GENERIC :: set => fhash_tbl_set_scalar + + PROCEDURE :: fhash_tbl_set_scalar_ptr + GENERIC :: set_ptr => fhash_tbl_set_scalar_ptr + + PROCEDURE :: fhash_tbl_get_int32, fhash_tbl_get_int64 + PROCEDURE :: fhash_tbl_get_float, fhash_tbl_get_double + PROCEDURE :: fhash_tbl_get_char, fhash_tbl_get_logical + PROCEDURE :: fhash_tbl_get_data, fhash_tbl_get_raw + + GENERIC :: get => fhash_tbl_get_int32, fhash_tbl_get_int64 + GENERIC :: get => fhash_tbl_get_float, fhash_tbl_get_double + GENERIC :: get => fhash_tbl_get_char, fhash_tbl_get_logical + GENERIC :: get => fhash_tbl_get_data + GENERIC :: get_raw => fhash_tbl_get_raw + + PROCEDURE :: fhash_tbl_get_int32_ptr, fhash_tbl_get_int64_ptr + PROCEDURE :: fhash_tbl_get_float_ptr, fhash_tbl_get_double_ptr + PROCEDURE :: fhash_tbl_get_char_ptr, fhash_tbl_get_logical_ptr + PROCEDURE :: fhash_tbl_get_raw_ptr + + GENERIC :: get_ptr => fhash_tbl_get_int32_ptr, fhash_tbl_get_int64_ptr + GENERIC :: get_ptr => fhash_tbl_get_float_ptr, fhash_tbl_get_double_ptr + GENERIC :: get_ptr => fhash_tbl_get_char_ptr, fhash_tbl_get_logical_ptr + GENERIC :: get_raw_ptr => fhash_tbl_get_raw_ptr + + FINAL :: fhash_tbl_cleanup + +END TYPE fhash_tbl_t + +CONTAINS + +!> Allocate hash table +SUBROUTINE fhash_tbl_allocate(tbl, size) + + !> Table object to allocate + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Number of buckets in hash table + !> If ommited, `tbl` is allocated with `FHASH_DEFAULT_ALLOCATION` + INTEGER, INTENT(in), OPTIONAL :: size + + IF (PRESENT(size)) THEN + ALLOCATE (tbl%buckets(size)) + ELSE + ALLOCATE (tbl%buckets(FHASH_DEFAULT_ALLOCATION)) + END IF + +END SUBROUTINE fhash_tbl_allocate + +!> Finalizer for fhash_tbl_t +SUBROUTINE fhash_tbl_cleanup(tbl) + + !> Table object to allocate + TYPE(fhash_tbl_t), INTENT(inout) :: tbl + + INTEGER :: i + + IF (.NOT. ALLOCATED(tbl%buckets)) RETURN + + DO i = 1, SIZE(tbl%buckets) + + CALL sll_clean(tbl%buckets(i)) + + END DO + +END SUBROUTINE fhash_tbl_cleanup + +!> Unset a value in the table +!> +SUBROUTINE fhash_tbl_unset(tbl, key, stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Key to remove + CLASS(fhash_key_t), INTENT(in) :: key + + !> Status flag. Zero if successful. + !> Unsuccessful: FHASH_EMPTY_TABLE | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + INTEGER :: index + LOGICAL :: found + + IF (PRESENT(stat)) stat = 0 + + IF (.NOT. ALLOCATED(tbl%buckets)) THEN + IF (PRESENT(stat)) stat = FHASH_EMPTY_TABLE + RETURN + END IF + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + CALL sll_remove(tbl%buckets(index), key, found) + + IF (PRESENT(stat)) stat = MERGE(0, FHASH_KEY_NOT_FOUND, found) + +END SUBROUTINE fhash_tbl_unset + +!> Check if key exists in table +SUBROUTINE fhash_tbl_check_key(tbl, key, stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Status flag. Zero if key is found. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out) :: stat + + INTEGER :: index + LOGICAL :: found + TYPE(fhash_container_t), POINTER :: DATA + + IF (.NOT. ALLOCATED(tbl%buckets)) THEN + stat = FHASH_EMPTY_TABLE + RETURN + END IF + + stat = 0 + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + + CALL sll_find_in(tbl%buckets(index), key, DATA, found) + + stat = MERGE(0, FHASH_KEY_NOT_FOUND, found) + + RETURN + +END SUBROUTINE fhash_tbl_check_key + +!> Get stats about the hash table +subroutine fhash_tbl_stats(tbl,num_buckets,num_items,num_collisions,max_depth) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Number of buckets allocated in table + INTEGER, INTENT(out), OPTIONAL :: num_buckets + + !> Number of key-value pairs stored in table + INTEGER, INTENT(out), OPTIONAL :: num_items + + !> Number of hash collisions + INTEGER, INTENT(out), OPTIONAL :: num_collisions + + !> Maximum depth of bucket in table + INTEGER, INTENT(out), OPTIONAL :: max_depth + + INTEGER :: i, depth + + ! Initialise stats + IF (PRESENT(num_items)) num_items = 0 + IF (PRESENT(num_collisions)) num_collisions = 0 + IF (PRESENT(max_depth)) max_depth = 0 + IF (PRESENT(num_buckets)) num_buckets = 0 + + IF (.NOT. ALLOCATED(tbl%buckets)) RETURN + + IF (PRESENT(num_buckets)) THEN + num_buckets = SIZE(tbl%buckets) + END IF + + DO i = 1, SIZE(tbl%buckets) + + depth = node_depth(tbl%buckets(i)) + + IF (PRESENT(num_items)) num_items = num_items + depth + + IF (PRESENT(num_collisions)) num_collisions = num_collisions + & + MERGE(depth - 1, 0, depth > 1) + + IF (PRESENT(max_depth)) max_depth = MAX(max_depth, depth) + + END DO + +END SUBROUTINE fhash_tbl_stats + +!> Set/update a polymorphic scalar value in the table +!> +!> `tbl` is allocated with default size if not already allocated +SUBROUTINE fhash_tbl_set_scalar(tbl, key, VALUE, POINTER) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Key to set/update + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value for key + CLASS(*), INTENT(in), TARGET :: VALUE + + !> If .true., store a pointer to value instead of copying + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + INTEGER :: index + + IF (.NOT. ALLOCATED(tbl%buckets)) CALL fhash_tbl_allocate(tbl) + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + + CALL sll_push_node(tbl%buckets(index), key, VALUE, POINTER) + +END SUBROUTINE fhash_tbl_set_scalar + +!> Get wrapper routine for generic 'set_ptr' +!> +!> `tbl` is allocated with default size if not already allocated +SUBROUTINE fhash_tbl_set_scalar_ptr(tbl, key, VALUE) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Key to set/update + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value for key + CLASS(*), INTENT(in), TARGET :: VALUE + + CALL fhash_tbl_set_scalar(tbl, key, VALUE, POINTER=.TRUE.) + +END SUBROUTINE fhash_tbl_set_scalar_ptr + +!> Retrieve data container from the hash table +SUBROUTINE fhash_tbl_get_data(tbl, key, DATA, stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Copy of value retrieved for key + TYPE(fhash_container_t), POINTER :: DATA + + !> Status flag. Zero if successful. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + INTEGER :: index + LOGICAL :: found + + IF (.NOT. ALLOCATED(tbl%buckets)) THEN + IF (PRESENT(stat)) stat = FHASH_EMPTY_TABLE + RETURN + END IF + + IF (PRESENT(stat)) stat = 0 + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + + CALL sll_find_in(tbl%buckets(index), key, DATA, found) + + IF (.NOT. found) THEN + + IF (PRESENT(stat)) stat = FHASH_KEY_NOT_FOUND + RETURN + + END IF + +END SUBROUTINE fhash_tbl_get_data + +!> Get wrapper to retrieve a scalar intrinsic type value +subroutine fhash_tbl_get_intrinsic_scalar(tbl,key,i32,i64,r32,r64,char,raw,bool,stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value to retrieve + INTEGER(INT32), INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), INTENT(out), OPTIONAL :: i64 + REAL(sp), INTENT(out), OPTIONAL :: r32 + REAL(dp), INTENT(out), OPTIONAL :: r64 + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: char + LOGICAL, INTENT(out), OPTIONAL :: bool + CLASS(*), ALLOCATABLE, INTENT(out), OPTIONAL :: raw + + !> Status flag. Zero if successful. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | + !> `FHASH_FOUND_WRONG_TYPE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + LOGICAL :: type_match + INTEGER :: local_stat + TYPE(fhash_container_t), POINTER :: DATA + + CHARACTER(:), ALLOCATABLE :: char_temp + + IF (PRESENT(stat)) stat = 0 + + CALL fhash_tbl_get_data(tbl, key, DATA, local_stat) + + IF (local_stat /= 0) THEN + IF (PRESENT(stat)) stat = local_stat + RETURN + END IF + + IF (PRESENT(char)) THEN ! (Work-around for weird gfortran bug re char dummy) + + CALL DATA%get(i32, i64, r32, r64, char_temp, bool, raw, type_match) + + IF (type_match) char = char_temp + + ELSE + + CALL DATA%get(i32, i64, r32, r64, bool=bool, raw=raw, match=type_match) + + END IF + + IF (.NOT. type_match) THEN + IF (PRESENT(stat)) stat = FHASH_FOUND_WRONG_TYPE + RETURN + END IF + +END SUBROUTINE fhash_tbl_get_intrinsic_scalar + +!> Get wrapper to retrieve a scalar intrinsic type pointer +subroutine fhash_tbl_get_intrinsic_scalar_ptr(tbl,key,i32,i64,r32,r64,char,bool,raw,stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value to retrieve + INTEGER(INT32), POINTER, INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), POINTER, INTENT(out), OPTIONAL :: i64 + REAL(sp), POINTER, INTENT(out), OPTIONAL :: r32 + REAL(dp), POINTER, INTENT(out), OPTIONAL :: r64 + CHARACTER(:), POINTER, INTENT(out), OPTIONAL :: char + LOGICAL, POINTER, INTENT(out), OPTIONAL :: bool + CLASS(*), POINTER, INTENT(out), OPTIONAL :: raw + + !> Status flag. Zero if successful. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | + !> `FHASH_FOUND_WRONG_TYPE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + LOGICAL :: type_match + INTEGER :: local_stat + TYPE(fhash_container_t), POINTER :: DATA + + CHARACTER(:), POINTER :: char_temp + + IF (PRESENT(stat)) stat = 0 + + CALL fhash_tbl_get_data(tbl, key, DATA, local_stat) + + IF (local_stat /= 0) THEN + IF (PRESENT(stat)) stat = local_stat + RETURN + END IF + + IF (PRESENT(char)) THEN ! (Work-around for weird gfortran bug re char dummy) + + CALL DATA%get_ptr(i32, i64, r32, r64, char_temp, bool, raw, type_match) + + IF (type_match) char => char_temp + + ELSE + + CALL DATA%get_ptr(i32, i64, r32, r64, bool=bool, raw=raw, match=type_match) + + END IF + + IF (.NOT. type_match) THEN + IF (PRESENT(stat)) stat = FHASH_FOUND_WRONG_TYPE + RETURN + END IF + +END SUBROUTINE fhash_tbl_get_intrinsic_scalar_ptr + +!> Get wrapper to directly retrieve a scalar int32 value +SUBROUTINE fhash_tbl_get_int32(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT32), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, i32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int32 + +!> Get wrapper to directly retrieve a scalar int64 value +SUBROUTINE fhash_tbl_get_int64(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT64), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, i64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int64 + +!> Get wrapper to directly retrieve a scalar float value +SUBROUTINE fhash_tbl_get_float(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(sp), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, r32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_float + +!> Get wrapper to directly retrieve a scalar double value +SUBROUTINE fhash_tbl_get_double(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(dp), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, r64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_double + +!> Get wrapper to directly retrieve a scalar character value +SUBROUTINE fhash_tbl_get_char(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CHARACTER(:), ALLOCATABLE, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, char=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_char + +!> Get wrapper to directly retrieve a scalar logical value +SUBROUTINE fhash_tbl_get_logical(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + LOGICAL, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, bool=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_logical + +!> Get wrapper to directly retrieve underlying polymorhpic scalar value +SUBROUTINE fhash_tbl_get_raw(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CLASS(*), ALLOCATABLE, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, raw=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_raw + +!> Get wrapper to directly retrieve a scalar int32 value +SUBROUTINE fhash_tbl_get_int32_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT32), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, i32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int32_ptr + +!> Get wrapper to directly retrieve a scalar int64 value +SUBROUTINE fhash_tbl_get_int64_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT64), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, i64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int64_ptr + +!> Get wrapper to directly retrieve a scalar float value +SUBROUTINE fhash_tbl_get_float_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(sp), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, r32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_float_ptr + +!> Get wrapper to directly retrieve a scalar double value +SUBROUTINE fhash_tbl_get_double_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(dp), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, r64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_double_ptr + +!> Get wrapper to directly retrieve a scalar character value +SUBROUTINE fhash_tbl_get_char_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CHARACTER(:), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, char=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_char_ptr + +!> Get wrapper to directly retrieve a scalar logical value +SUBROUTINE fhash_tbl_get_logical_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + LOGICAL, POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, bool=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_logical_ptr + +!> Get wrapper to directly retrieve underlying polymorhpic scalar value +SUBROUTINE fhash_tbl_get_raw_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CLASS(*), POINTER, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, raw=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_raw_ptr + +END MODULE fhash_tbl diff --git a/src/modules/Fhash/src/fhash_tbl_iter.F90 b/src/modules/Fhash/src/fhash_tbl_iter.F90 new file mode 100644 index 000000000..45188529d --- /dev/null +++ b/src/modules/Fhash/src/fhash_tbl_iter.F90 @@ -0,0 +1,83 @@ +MODULE fhash_tbl_iter +USE fhash_tbl, ONLY: fhash_tbl_t +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_data_container, ONLY: fhash_container_t +USE fhash_sll +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_iter_t + +!> Iterator type for iterating over hash table items +TYPE fhash_iter_t + + TYPE(fhash_tbl_t), POINTER :: tbl => NULL() + + INTEGER :: bucket = 1 + INTEGER :: depth = 1 + +CONTAINS + PROCEDURE :: next => fhash_iter_next + PROCEDURE :: reset => fhash_iter_reset +END TYPE fhash_iter_t + +INTERFACE fhash_iter_t + MODULE PROCEDURE :: fhash_iter_init +END INTERFACE fhash_iter_t + +CONTAINS + +!> Initialise fhash iterator +FUNCTION fhash_iter_init(tbl) RESULT(iter) + TYPE(fhash_tbl_t), INTENT(in), TARGET :: tbl + TYPE(fhash_iter_t) :: iter + + iter%tbl => tbl + +END FUNCTION fhash_iter_init + +!> Return next item from iterator +FUNCTION fhash_iter_next(iter, key, DATA) RESULT(found) + CLASS(fhash_iter_t), INTENT(inout) :: iter + CLASS(fhash_key_t), INTENT(out), ALLOCATABLE :: key + CLASS(*), ALLOCATABLE, INTENT(out) :: DATA + LOGICAL :: found + + TYPE(fhash_container_t), POINTER :: data_container + CLASS(*), POINTER :: data_out + + found = .FALSE. + + IF (.NOT. ASSOCIATED(iter%tbl)) RETURN + + DO WHILE (.NOT. found) + IF (iter%bucket > SIZE(iter%tbl%buckets)) RETURN + IF (.NOT. ALLOCATED(iter%tbl%buckets(iter%bucket)%key)) THEN + iter%bucket = iter%bucket + 1 + CYCLE + END IF + call sll_get_at(iter%tbl%buckets(iter%bucket),iter%depth,key,data_container,found) + IF (iter%depth > node_depth(iter%tbl%buckets(iter%bucket))) THEN + iter%bucket = iter%bucket + 1 + iter%depth = 1 + ELSE + iter%depth = iter%depth + 1 + END IF + END DO + + IF (found) THEN + CALL data_container%get(raw=DATA) ! Extract underlying polymorphic data + END IF + +END FUNCTION fhash_iter_next + +!> Reset iterator to beginning +SUBROUTINE fhash_iter_reset(iter) + CLASS(fhash_iter_t), INTENT(inout) :: iter + + iter%bucket = 1 + iter%depth = 1 + +END SUBROUTINE fhash_iter_reset + +END MODULE fhash_tbl_iter From 96b733a3bd7cd2e8fa3a21b01ea398e2582a4949 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 11:42:35 +0900 Subject: [PATCH 009/117] Enhancements in Finite Element Fixes #176 --- .../AbstractFE/src/AbstractFE_Class.F90 | 3 +- .../FiniteElement/src/FiniteElement_Class.F90 | 58 ++++++++++- .../src/FiniteElement_Class@Methods.F90 | 99 +++++++++++++------ 3 files changed, 125 insertions(+), 35 deletions(-) diff --git a/src/modules/AbstractFE/src/AbstractFE_Class.F90 b/src/modules/AbstractFE/src/AbstractFE_Class.F90 index 0df6d4f3a..8f104c19b 100644 --- a/src/modules/AbstractFE/src/AbstractFE_Class.F90 +++ b/src/modules/AbstractFE/src/AbstractFE_Class.F90 @@ -766,7 +766,8 @@ MODULE SUBROUTINE fe_GetQuadraturePoints1(obj, quad, quadratureType, & !! GaussChebyshevRadau, GaussChebyshevRadauLeft !! GaussChebyshevRadauRight INTEGER(I4B), OPTIONAL, INTENT(IN) :: order(:) - !! Order of integrand, either order or nips should be present + !! Order of integrand + !! either the order or the nips should be present !! Both nips and order should not be present INTEGER(I4B), OPTIONAL, INTENT(IN) :: nips(:) !! Number of integration points required diff --git a/src/modules/FiniteElement/src/FiniteElement_Class.F90 b/src/modules/FiniteElement/src/FiniteElement_Class.F90 index 84ace8b9d..d453184d3 100644 --- a/src/modules/FiniteElement/src/FiniteElement_Class.F90 +++ b/src/modules/FiniteElement/src/FiniteElement_Class.F90 @@ -46,6 +46,8 @@ MODULE FiniteElement_Class PROCEDURE, PUBLIC, PASS(obj) :: Initiate => fe_Initiate !! Constructor method for AbstractFE element !! This method can be overloaded by Subclass of this abstract class. + PROCEDURE, PUBLIC, PASS( obj ) :: InitiateLagrangeFE => & + & fe_InitiateLagrangeFE PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & fe_CheckEssentialParam END TYPE FiniteElement_ @@ -88,6 +90,50 @@ MODULE SUBROUTINE fe_Initiate(obj, param) END SUBROUTINE fe_Initiate END INTERFACE +!---------------------------------------------------------------------------- +! Initiate@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 27 Aug 2022 +! summary: Initiates an instance of the finite element + +INTERFACE + MODULE SUBROUTINE fe_InitiateLagrangeFE(obj, nsd, & + & elemType, baseContinuity, baseInterpolation, ipType, & + & basisType, alpha, beta, lambda, order) + CLASS(FiniteElement_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: nsd + !! Number of spatial dimension + INTEGER(I4B), INTENT(IN) :: elemType + !! Type of finite element + !! Line, Triangle, Quadrangle, Tetrahedron, Prism, Pyramid, + !! Hexahedron + CHARACTER(*), INTENT(IN) :: baseContinuity + !! Continuity or Conformity of basis function. + !! H1* (default), HDiv, HCurl, DG + CHARACTER(*), INTENT(IN) :: baseInterpolation + !! Basis function family used for interpolation. + !! LagrangeInterpolation, LagrangePolynomial + INTEGER(I4B), INTENT(IN) :: ipType + !! Interpolation point type, It is required when + !! baseInterpol is LagrangePolynomial. It can take following + !! values: + !! Legendre, Chebyshev, Ultraspherical, Equidistance, Jacobi + INTEGER(I4B), INTENT(IN) :: basisType + !! Basis type: + !! Legendre, Lobatto, Ultraspherical, Jacobi, Monomial + REAL(DFP), INTENT(IN) :: alpha + !! Jacobi parameter + REAL(DFP), INTENT(IN) :: beta + !! Jacobi parameter + REAL(DFP), INTENT(IN) :: lambda + !! Ultraspherical parameters + INTEGER(I4B), INTENT(IN) :: order + !! Isotropic Order of finite element + END SUBROUTINE fe_InitiateLagrangeFE +END INTERFACE + !---------------------------------------------------------------------------- ! Deallocate@Methods !---------------------------------------------------------------------------- @@ -150,9 +196,6 @@ MODULE SUBROUTINE SetFiniteElementParam( & !! Hexahedron CHARACTER(*), INTENT(IN) :: baseContinuity !! Continuity or Conformity of basis function. - !! This parameter is used to determine the nodal coordinates of - !! reference element, when xij is not present. - !! If xij is present then this parameter is ignored !! H1* (default), HDiv, HCurl, DG CHARACTER(*), INTENT(IN) :: baseInterpolation !! Basis function family used for interpolation. @@ -167,9 +210,13 @@ MODULE SUBROUTINE SetFiniteElementParam( & INTEGER(I4B), OPTIONAL, INTENT(IN) :: ipType !! Interpolation point type, It is required when !! baseInterpol is LagrangePolynomial + !! Legendre, Chebyshev, Ultraspherical, Equidistance + !! Jacobi INTEGER(I4B), OPTIONAL, INTENT(IN) :: basisType(:) - !! Basis type: Legendre, Lobatto, Ultraspherical, + !! Basis type: + !! Legendre, Lobatto, Ultraspherical, !! Jacobi, Monomial + !! Basis in x, y, and z direction. REAL(DFP), OPTIONAL, INTENT(IN) :: alpha(:) !! Jacobi parameter REAL(DFP), OPTIONAL, INTENT(IN) :: beta(:) @@ -198,10 +245,11 @@ END SUBROUTINE SetFiniteElementParam ! summary: Initiate vector of FiniteElement pointers INTERFACE Initiate - MODULE SUBROUTINE fe_Initiate1(obj, param, dom) + MODULE SUBROUTINE fe_Initiate1(obj, param, dom, dim) TYPE(FiniteElementPointer_), ALLOCATABLE, INTENT(INOUT) :: obj(:) TYPE(ParameterList_), INTENT(IN) :: param CLASS(Domain_), INTENT(IN) :: dom + INTEGER(I4B), INTENT(IN) :: dim END SUBROUTINE fe_Initiate1 END INTERFACE Initiate diff --git a/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 b/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 index b5f9e9de3..b91075abf 100644 --- a/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 +++ b/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 @@ -20,7 +20,7 @@ CONTAINS !---------------------------------------------------------------------------- -! Initiate +! Initiate !---------------------------------------------------------------------------- MODULE PROCEDURE fe_Initiate @@ -28,7 +28,7 @@ END PROCEDURE fe_Initiate !---------------------------------------------------------------------------- -! CheckEssentialParam +! CheckEssentialParam !---------------------------------------------------------------------------- MODULE PROCEDURE fe_CheckEssentialParam @@ -41,22 +41,22 @@ MODULE PROCEDURE SetFiniteElementParam CALL SetAbstractFEParam( & -& param=param, & -& prefix=myprefix, & -& nsd=nsd, & -& elemType=elemType, & -& baseContinuity=baseContinuity, & -& baseInterpolation=baseInterpolation, & -& ipType=ipType, & -& basisType=basisType, & -& alpha=alpha, & -& beta=beta, & -& lambda=lambda, & -& order=order, & -& anisoOrder=anisoOrder, & -& edgeOrder=edgeOrder, & -& faceOrder=faceOrder, & -& cellOrder=cellOrder) + & param=param, & + & prefix=myprefix, & + & nsd=nsd, & + & elemType=elemType, & + & baseContinuity=baseContinuity, & + & baseInterpolation=baseInterpolation, & + & ipType=ipType, & + & basisType=basisType, & + & alpha=alpha, & + & beta=beta, & + & lambda=lambda, & + & order=order, & + & anisoOrder=anisoOrder, & + & edgeOrder=edgeOrder, & + & faceOrder=faceOrder, & + & cellOrder=cellOrder) END PROCEDURE SetFiniteElementParam !---------------------------------------------------------------------------- @@ -97,32 +97,73 @@ MODULE PROCEDURE fe_Initiate1 CHARACTER(*), PARAMETER :: myName = "fe_Initiate1()" TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr, ii, tElemType -INTEGER(I4B), ALLOCATABLE :: elemType(:) +INTEGER(I4B) :: ierr, ii, tsize +INTEGER(I4B), ALLOCATABLE :: elemType(:), order(:) sublist => NULL() -IF (.NOT. param%isSubList(key=myPrefix)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[ARGUMENT ERROR] :: '//myprefix//' should be a sublist') -END IF +IF (.NOT. param%isSubList(key=myPrefix)) RETURN ierr = param%GetSubList(key=myprefix, sublist=sublist) -elemType = dom%GetElemType(dim=-1_I4B) -tElemType = SIZE(elemType) +IF (ierr .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured while getting'// & + & ' the sublist from param.') +END IF + +elemType = dom%GetElemType(dim=dim) +order = dom%GetOrder(dim=dim) +tsize = SIZE(elemType) CALL DEALLOCATE (obj) -ALLOCATE(obj(tElemType) ) +ALLOCATE (obj(tsize)) -DO ii = 1, SIZE(elemType) +DO ii = 1, tsize ierr = sublist%Set(key=myprefix//"/elemType", VALUE=elemType(ii)) - ALLOCATE(FiniteElement_::obj(ii)%ptr) + ierr = sublist%Set(key=myprefix//"/order", VALUE=order(ii)) + ALLOCATE (FiniteElement_ :: obj(ii)%ptr) CALL obj(ii)%ptr%Initiate(param=param) END DO sublist => NULL() IF (ALLOCATED(elemType)) DEALLOCATE (elemType) +IF (ALLOCATED(order)) DEALLOCATE (order) END PROCEDURE fe_Initiate1 +!---------------------------------------------------------------------------- +! InitiateLagrangeFE +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_InitiateLagrangeFE +TYPE(ParameterList_) :: param +CHARACTER(*), PARAMETER :: myName="fe_InitiateLagrangeFE()" + +IF (baseInterpolation .NE. "LagrangePolynomial" & + & .OR. baseInterpolation .NE. "LagrangeInterpolation") THEN + CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[ARG ERROR] :: This routine is valid for baseInterpolation = ' // & + & 'LagrangePolynomial or LagrangeInterpolation ' // & + & ' given value of baseInterpolation is ' // trim(baseInterpolation)) +END IF + +CALL param%Initiate() +CALL SetFiniteElementParam( & + & param=param, & + & nsd=nsd, & + & elemType=elemType, & + & baseContinuity=baseContinuity, & + & baseInterpolation=baseInterpolation, & + & ipType=ipType, & + & basisType=[basisType], & + & alpha=[alpha], & + & beta=[beta], & + & lambda=[lambda], & + & order=order) + +CALL obj%Initiate(param) + +CALL param%DEALLOCATE() +END PROCEDURE fe_InitiateLagrangeFE + END SUBMODULE Methods From 084b881060a384e8942b620cff6cd31becf036f5 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 15:29:26 +0900 Subject: [PATCH 010/117] Major enhancements in EASIFEM - enhancements in AbstractBC - adding fhash - toml support --- cmake/Compiler.cmake | 29 +- cmake/Config.cmake.in | 2 + cmake/addGmsh-old.cmake | 35 -- cmake/addGmsh.cmake | 30 +- cmake/targetCompileDefs.cmake | 4 +- cmake/targetLinkLibs.cmake | 43 ++ install.py | 4 +- src/modules/AbstractBC/CMakeLists.txt | 19 +- src/modules/AbstractBC/src/AbstractBC.toml | 61 -- .../AbstractBC/src/AbstractBC_Class.F90 | 288 +++------ .../AbstractFE/src/AbstractFE_Class.F90 | 3 +- .../DirichletBC/src/DirichletBC_Class.F90 | 109 ++-- src/modules/Fhash/CMakeLists.txt | 19 - src/modules/Fhash/src/fhash.F90 | 14 - .../Fhash/src/fhash_data_container.F90 | 241 -------- src/modules/Fhash/src/fhash_fnv.F90 | 181 ------ src/modules/Fhash/src/fhash_key/base.F90 | 42 -- src/modules/Fhash/src/fhash_key/char.F90 | 76 --- src/modules/Fhash/src/fhash_key/int32.F90 | 76 --- src/modules/Fhash/src/fhash_key/int32_1d.F90 | 82 --- src/modules/Fhash/src/fhash_key/int64.F90 | 76 --- src/modules/Fhash/src/fhash_key/int64_1d.F90 | 82 --- src/modules/Fhash/src/fhash_sll.F90 | 277 --------- src/modules/Fhash/src/fhash_tbl.F90 | 571 ------------------ src/modules/Fhash/src/fhash_tbl_iter.F90 | 83 --- .../FiniteElement/src/FiniteElement_Class.F90 | 58 +- src/modules/Toml/CMakeLists.txt | 22 - src/modules/Toml/src/TomlUtility.F90 | 302 --------- .../AbstractBC_Class@ConstructorMethods.F90 | 241 ++++---- .../src/AbstractBC_Class@GetMethods.F90 | 29 +- .../src/AbstractBC_Class@IOMethods.F90 | 282 +-------- .../src/AbstractBC_Class@SetMethods.F90 | 280 +++++---- .../DirichletBC_Class@ConstructorMethods.F90 | 48 +- .../src/DirichletBC_Class@GetMethods.F90 | 8 - .../src/DirichletBC_Class@IOMethods.F90 | 99 --- .../src/FiniteElement_Class@Methods.F90 | 99 +-- src/submodules/Toml/CMakeLists.txt | 22 - .../Toml/src/TomlUtility@GetMethods.F90 | 199 ------ 38 files changed, 588 insertions(+), 3548 deletions(-) delete mode 100644 cmake/addGmsh-old.cmake delete mode 100644 src/modules/AbstractBC/src/AbstractBC.toml delete mode 100644 src/modules/Fhash/CMakeLists.txt delete mode 100644 src/modules/Fhash/src/fhash.F90 delete mode 100644 src/modules/Fhash/src/fhash_data_container.F90 delete mode 100644 src/modules/Fhash/src/fhash_fnv.F90 delete mode 100644 src/modules/Fhash/src/fhash_key/base.F90 delete mode 100644 src/modules/Fhash/src/fhash_key/char.F90 delete mode 100644 src/modules/Fhash/src/fhash_key/int32.F90 delete mode 100644 src/modules/Fhash/src/fhash_key/int32_1d.F90 delete mode 100644 src/modules/Fhash/src/fhash_key/int64.F90 delete mode 100644 src/modules/Fhash/src/fhash_key/int64_1d.F90 delete mode 100644 src/modules/Fhash/src/fhash_sll.F90 delete mode 100644 src/modules/Fhash/src/fhash_tbl.F90 delete mode 100644 src/modules/Fhash/src/fhash_tbl_iter.F90 delete mode 100644 src/modules/Toml/CMakeLists.txt delete mode 100644 src/modules/Toml/src/TomlUtility.F90 delete mode 100644 src/submodules/Toml/CMakeLists.txt delete mode 100644 src/submodules/Toml/src/TomlUtility@GetMethods.F90 diff --git a/cmake/Compiler.cmake b/cmake/Compiler.cmake index 067043f78..b3a46043b 100644 --- a/cmake/Compiler.cmake +++ b/cmake/Compiler.cmake @@ -31,34 +31,7 @@ ENDIF() IF (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU" OR Fortran_COMPILER_NAME MATCHES "gfortran*") LIST(APPEND FORTRAN_FLAGS "-ffree-form" "-ffree-line-length-none" "-std=f2018" "-fimplicit-none" ) LIST(APPEND FORTRAN_FLAGS_RELEASE "-O3" ) - - IF(APPLE) - LIST( - APPEND - FORTRAN_FLAGS_DEBUG - "-fbounds-check" - "-g" - "-fbacktrace" - "-Wextra" - "-Wall" - # "-fprofile-arcs" - "-ftest-coverage" - "-Wimplicit-interface" - ) - ELSE() - LIST( - APPEND - FORTRAN_FLAGS_DEBUG - "-fbounds-check" - "-g" - "-fbacktrace" - "-Wextra" - "-Wall" - # "-fprofile-arcs" - "-ftest-coverage" - "-Wimplicit-interface" - ) - ENDIF() + LIST(APPEND FORTRAN_FLAGS_DEBUG "-fbounds-check" "-g" "-fbacktrace" "-Wextra" "-Wall" "-fprofile-arcs" "-ftest-coverage" "-Wimplicit-interface" ) ELSEIF(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel" OR Fortran_COMPILER_NAME MATCHES "ifort*") LIST(APPEND FORTRAN_FLAGS "-r8" "-W1") diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in index a8049d31c..53bcc9b97 100644 --- a/cmake/Config.cmake.in +++ b/cmake/Config.cmake.in @@ -28,6 +28,8 @@ # find_package(easifemBase 1.0.0 CONFIG REQUIRED) # # The following variables can be set to guide the search for this package: +# +# @PACKAGE_INIT@ diff --git a/cmake/addGmsh-old.cmake b/cmake/addGmsh-old.cmake deleted file mode 100644 index 897195819..000000000 --- a/cmake/addGmsh-old.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# 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 -# -#GMSH SDK -IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) - OPTION( USE_GMSH_SDK OFF ) - IF( USE_GMSH_SDK ) - LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) - IF( UNIX ) - IF(APPLE) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) - ELSE() - # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) - ENDIF() - ENDIF() - TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) - MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) - ELSE() - MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) - ENDIF() -ENDIF() diff --git a/cmake/addGmsh.cmake b/cmake/addGmsh.cmake index 39cecb6e8..897195819 100644 --- a/cmake/addGmsh.cmake +++ b/cmake/addGmsh.cmake @@ -19,27 +19,15 @@ IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) OPTION( USE_GMSH_SDK OFF ) IF( USE_GMSH_SDK ) LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) - FIND_PACKAGE(PkgConfig REQUIRED) - FIND_LIBRARY(GMSH_LIBRARY - NAMES gmsh gmsh.4.12 - PATHS "$ENV{CONDA_PREFIX}/lib" "/opt/homebrew/lib" ) - # PATHS "/opt/homebrew/lib" ) - SET(GMSH_LIBRARIES ${GMSH_LIBRARY}) - - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS( - GMSH DEFAULT_MSG - GMSH_LIBRARIES - ) - - # SET(GMSH_LIBRARIES "$ENV{CONDA_PREFIX}/lib/libgmsh.so") - - TARGET_LINK_LIBRARIES( - ${PROJECT_NAME} - PUBLIC - ${GMSH_LIBRARIES} - ) - + IF( UNIX ) + IF(APPLE) + SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) + ELSE() + # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) + SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) + ENDIF() + ENDIF() + TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) ELSE() MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) diff --git a/cmake/targetCompileDefs.cmake b/cmake/targetCompileDefs.cmake index b8c68788e..f7c9ae517 100644 --- a/cmake/targetCompileDefs.cmake +++ b/cmake/targetCompileDefs.cmake @@ -38,10 +38,10 @@ ENDIF() LIST( APPEND TARGET_COMPILE_DEF "-D${CMAKE_HOST_SYSTEM_NAME}_SYSTEM" ) #DEFINE DEBUG -IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug") +IF( $ ) LIST( APPEND TARGET_COMPILE_DEF "-DDEBUG_VER" ) ENDIF() #ADD TO PROJECT TARGET_COMPILE_DEFINITIONS( ${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_DEF} ) -MESSAGE( STATUS "COMPILE DEFINITIONS USED ARE ${TARGET_COMPILE_DEF}") +MESSAGE( STATUS "COMPILE DEFINITIONS USED ARE ${TARGET_COMPILE_DEF}") \ No newline at end of file diff --git a/cmake/targetLinkLibs.cmake b/cmake/targetLinkLibs.cmake index 024a1e8c1..fb29a3ee5 100644 --- a/cmake/targetLinkLibs.cmake +++ b/cmake/targetLinkLibs.cmake @@ -16,6 +16,49 @@ # # +# Link libs to the project + +#.................................................................... +# +#.................................................................... + +FUNCTION(FIND_EASIFEM_DEPENDENCY EXT_PKG_LIST) + FOREACH(p ${EXT_PKG_LIST}) + FIND_PACKAGE( ${p} REQUIRED ) + IF( ${p}_FOUND ) + MESSAGE(STATUS "FOUND ${p}") + ELSE() + MESSAGE(ERROR "NOT FOUND ${p}") + ENDIF() + ENDFOREACH() +ENDFUNCTION(FIND_EASIFEM_DEPENDENCY) + +#.................................................................... +# +#.................................................................... + +FUNCTION(LINK_EASIFEM_DEPENDENCY EXT_PKG_LIST PROJECT_NAME) + FOREACH(p ${EXT_PKG_LIST}) + TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${p}::${p} ) + ENDFOREACH() +ENDFUNCTION(LINK_EASIFEM_DEPENDENCY) + +#.................................................................... +# +#.................................................................... + +IF( ${PROJECT_NAME} MATCHES "easifemBase" ) + IF( USE_LAPACK95 ) + LIST(APPEND EXT_PKGS LAPACK95) + LIST( APPEND TARGET_COMPILE_DEF "-DUSE_LAPACK95" ) + ENDIF() + + LIST(APPEND EXT_PKGS Sparsekit) + + FIND_EASIFEM_DEPENDENCY( "${EXT_PKGS}" ) + LINK_EASIFEM_DEPENDENCY( "${EXT_PKGS}" "${PROJECT_NAME}" ) +ENDIF() + #.................................................................... # #.................................................................... diff --git a/install.py b/install.py index 4e999f3d8..c81816614 100755 --- a/install.py +++ b/install.py @@ -20,8 +20,8 @@ else: cmake_def = "" cmake_def += '-G "Ninja"' - cmake_def += " -D USE_GMSH_SDK:BOOL=ON" - cmake_def += " -D CMAKE_BUILD_TYPE=Debug" + cmake_def += " -D USE_GMSH_SDK:BOOL=OFF" + cmake_def += " -D CMAKE_BUILD_TYPE:STRING=Release" cmake_def += " -D BUILD_SHARED_LIBS:BOOL=ON" cmake_def += " -D CMAKE_INSTALL_PREFIX:PATH=${EASIFEM_CLASSES}" print("CMAKE DEF : ", cmake_def) diff --git a/src/modules/AbstractBC/CMakeLists.txt b/src/modules/AbstractBC/CMakeLists.txt index ebba19c43..47e087846 100644 --- a/src/modules/AbstractBC/CMakeLists.txt +++ b/src/modules/AbstractBC/CMakeLists.txt @@ -1,22 +1,5 @@ -# 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}/AbstractBC_Class.F90 -) +) \ No newline at end of file diff --git a/src/modules/AbstractBC/src/AbstractBC.toml b/src/modules/AbstractBC/src/AbstractBC.toml deleted file mode 100644 index 5d7f409b5..000000000 --- a/src/modules/AbstractBC/src/AbstractBC.toml +++ /dev/null @@ -1,61 +0,0 @@ -[bc] -name="DirichletBC" -idof=1 -nodalValueType="Constant" # Time, SpaceTime, Space -useFunction=false -isNormal=false -isTangent=false -useExternal=false -value=20.0 # when nodalValueType=Constant -# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Space -# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Time -# value=[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]] # SpaceTime -spaceFunction="lua script f(x)" -timeFunction="lua script f(t)" -spaceTimeFunction="lua script f(x, t)" - -[bc.boundary] -isSelectionByMeshID = false -isSelectionByElemNum = false -isSelectionByBox = false -isSelectionByNodeNum = false - -[bc.boundary.meshID] -point = [1,2,3] # "filename.txt" -line = [1,2,3,4] # "filename.txt" -surface = [1,2,3] # "filename.txt" -volume = [1,2,3] # "filename.txt" - -[bc.boundary.box] -point = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} -] - -line = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} -] - -surface = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} -] - -volume = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} -] - -[bc.boundary.elemNum] -point = [1,2,3] -line = [1,2,3] -surface=[1,2,3] -volume=[1,2,3] - -[bc.boundary.nodeNum] -point = [1,2,3] -line = [1,2,3] -surface=[1,2,3] -volume=[1,2,3] - diff --git a/src/modules/AbstractBC/src/AbstractBC_Class.F90 b/src/modules/AbstractBC/src/AbstractBC_Class.F90 index ca1e9526f..a044df100 100644 --- a/src/modules/AbstractBC/src/AbstractBC_Class.F90 +++ b/src/modules/AbstractBC/src/AbstractBC_Class.F90 @@ -13,6 +13,7 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see +! MODULE AbstractBC_Class USE GlobalData @@ -23,28 +24,9 @@ MODULE AbstractBC_Class USE Domain_Class USE HDF5File_Class USE FPL, ONLY: ParameterList_ -USE tomlf, ONLY: toml_table -USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractBC_Class" -CHARACTER(*), PARAMETER :: default_name = "AbstractBC" -INTEGER(I4B), PARAMETER :: default_idof = 0_I4B -INTEGER(I4B), PARAMETER :: default_nodalValueType = -1_I4B -CHARACTER(*) , PARAMETER :: default_nodalValueType_char = "NONE" -LOGICAL(LGT), PARAMETER :: default_useFunction = .FALSE. -LOGICAL(LGT), PARAMETER :: default_isNormal = .FALSE. -LOGICAL(LGT), PARAMETER :: default_isTangent = .FALSE. -LOGICAL(LGT), PARAMETER :: default_useExternal = .FALSE. - -PUBLIC :: AbstractBC_ -PUBLIC :: AbstractBCPointer_ -PUBLIC :: AbstractBCDeallocate -PUBLIC :: AbstractBCcheckEssentialParam -PUBLIC :: SetAbstractBCParam -PUBLIC :: AbstractBCInitiate -PUBLIC :: AbstractBCImportFromToml -PUBLIC :: AbstractBCImportParamFromToml !---------------------------------------------------------------------------- ! AbstractBC_ @@ -56,23 +38,23 @@ MODULE AbstractBC_Class TYPE, ABSTRACT :: AbstractBC_ LOGICAL(LGT) :: isInitiated = .FALSE. - !! It is true if the object is initiated + !! TYPE(String) :: name !! name of boundary condition - INTEGER(I4B) :: idof = default_idof + INTEGER(I4B) :: idof = 0 !! degree of freedom number - INTEGER(I4B) :: nodalValueType = default_nodalValueType + INTEGER(I4B) :: nodalValueType = -1 !! Constant !! Space !! Time !! SpaceTime - LOGICAL(LGT) :: useFunction = default_useFunction + LOGICAL(LGT) :: useFunction = .FALSE. !! True if the boundary condition is analytical - LOGICAL(LGT) :: isNormal = default_isNormal + LOGICAL(LGT) :: isNormal = .FALSE. !! True if the boundary condition is normal to the boundary - LOGICAL(LGT) :: isTangent = default_isTangent + LOGICAL(LGT) :: isTangent = .FALSE. !! True if the boundary condition is tangent to the boundary - LOGICAL(LGT) :: useExternal = default_useExternal + LOGICAL(LGT) :: useExternal = .FALSE. !! if true then nodal values are used externally !! depending upon the context. !! Basically we do not use the nodal value stored in the @@ -95,46 +77,25 @@ MODULE AbstractBC_Class !! Domain CONTAINS PRIVATE - - ! CONSTRUCTOR: - ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => bc_Deallocate - PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & - & bc_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID + PROCEDURE, PUBLIC, PASS(obj) :: Get => bc_Get + PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction + PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo + PROCEDURE, PUBLIC, PASS(obj) :: & + & CheckEssentialParam => bc_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate - - ! IO: - ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => bc_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => bc_Export PROCEDURE, PUBLIC, PASS(obj) :: Display => bc_Display - PROCEDURE, PASS(obj) :: ImportFromToml1 => bc_ImportFromToml1 - PROCEDURE, PASS(obj) :: ImportFromToml2 => bc_ImportFromToml2 - GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & - & ImportFromToml2 - !! Import abstract kernel from toml - PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & - & bc_ImportParamFromToml - - ! SET: - ! @SetMethods - PROCEDURE, PUBLIC, PASS(obj) :: Set => bc_Set - - ! GET: - ! @GetMethods - PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID - PROCEDURE, PUBLIC, PASS(obj) :: Get1 => bc_Get - PROCEDURE, PUBLIC, PASS(obj) :: Get2 => bc_GetFEVar - GENERIC, PUBLIC :: Get => Get1, Get2 - PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction - PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo - PROCEDURE, PUBLIC, PASS(obj) :: GetQuery => bc_GetQuery - PROCEDURE, PUBLIC, PASS(obj) :: GetParam => bc_GetQuery - PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix PROCEDURE, PUBLIC, PASS(obj) :: isUseFunction => bc_isUseFunction !! Returns true if the useFunction is true + PROCEDURE, PUBLIC, PASS(obj) :: Set => bc_Set + PROCEDURE, PUBLIC, PASS(obj) :: GetQuery => bc_GetQuery END TYPE AbstractBC_ +PUBLIC :: AbstractBC_ + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -143,32 +104,72 @@ MODULE AbstractBC_Class CLASS(AbstractBC_), POINTER :: ptr => NULL() END TYPE AbstractBCPointer_ +PUBLIC :: AbstractBCPointer_ + !---------------------------------------------------------------------------- ! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-14 -! summary: Check essential parameters - -INTERFACE AbstractBCcheckEssentialParam - MODULE SUBROUTINE bc_CheckEssentialParam(obj, param, prefix) +INTERFACE + MODULE SUBROUTINE bc_CheckEssentialParam(obj, param) CLASS(AbstractBC_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix END SUBROUTINE bc_CheckEssentialParam -END INTERFACE AbstractBCcheckEssentialParam +END INTERFACE !---------------------------------------------------------------------------- -! SetAbstractBCParam@ConstructorMethods +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(MeshSelection_), INTENT(IN) :: boundary + CLASS(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE bc_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. -! date: 2023-11-14 -! summary: Set abstract boundary condition parameters +! date: 2023-02-12 +! summary: Deallocate data + +INTERFACE + MODULE SUBROUTINE bc_Deallocate(obj) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + END SUBROUTINE bc_Deallocate +END INTERFACE + +INTERFACE AbstractBCDeallocate + MODULE PROCEDURE bc_Deallocate +END INTERFACE AbstractBCDeallocate + +PUBLIC :: AbstractBCDeallocate + +!---------------------------------------------------------------------------- +! AbstractBCcheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE AbstractBCcheckEssentialParam(obj, param, prefix) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), INTENT(IN) :: prefix + END SUBROUTINE AbstractBCcheckEssentialParam +END INTERFACE + +PUBLIC :: AbstractBCcheckEssentialParam + +!---------------------------------------------------------------------------- +! SetAbstractBCParam@ConstructorMethods +!---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & + MODULE SUBROUTINE setAbstractBCParam(param, prefix, & & name, idof, nodalValueType, useFunction, isNormal, isTangent, & & useExternal) TYPE(ParameterList_), INTENT(INOUT) :: param @@ -194,48 +195,31 @@ MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & !! default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useExternal !! default is false - END SUBROUTINE SetAbstractBCParam + END SUBROUTINE setAbstractBCParam END INTERFACE +PUBLIC :: setAbstractBCParam + !---------------------------------------------------------------------------- -! Initiate@ConstructorMethods +! AbstractBCInitiate@ConstructorMethods !---------------------------------------------------------------------------- -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-14 -! summary: Initiate abstract boundary condition - -INTERFACE AbstractBCInitiate - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) +INTERFACE + MODULE SUBROUTINE AbstractBCInitiate(obj, param, prefix, boundary, dom) CLASS(AbstractBC_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), INTENT(IN) :: prefix TYPE(MeshSelection_), INTENT(IN) :: boundary CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE AbstractBCInitiate - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-02-12 -! summary: Deallocate data + END SUBROUTINE AbstractBCInitiate +END INTERFACE -INTERFACE AbstractBCDeallocate - MODULE SUBROUTINE bc_Deallocate(obj) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - END SUBROUTINE bc_Deallocate -END INTERFACE AbstractBCDeallocate +PUBLIC :: AbstractBCInitiate !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-14 -! summary: Import AbstractBC from HDF5File - INTERFACE MODULE SUBROUTINE bc_Import(obj, hdf5, group, dom) CLASS(AbstractBC_), INTENT(INOUT) :: obj @@ -261,58 +245,6 @@ MODULE SUBROUTINE bc_Export(obj, hdf5, group) END SUBROUTINE bc_Export END INTERFACE -!---------------------------------------------------------------------------- -! ImportParamFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate param by reading the toml table - -INTERFACE AbstractBCImportParamFromToml - MODULE SUBROUTINE bc_ImportParamFromToml(obj, param, table) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(INOUT) :: param - TYPE(toml_table), INTENT(INOUT) :: table - END SUBROUTINE bc_ImportParamFromToml -END INTERFACE AbstractBCImportParamFromToml - -!---------------------------------------------------------------------------- -! ImportFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate param from the toml file - -INTERFACE AbstractBCImportFromToml - MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - TYPE(toml_table), INTENT(INOUT) :: table - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_ImportFromToml1 -END INTERFACE AbstractBCImportFromToml - -!---------------------------------------------------------------------------- -! ImportFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate kernel from the toml file - -INTERFACE AbstractBCImportFromToml - MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & - & filename, printToml) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - CLASS(Domain_), TARGET, INTENT(IN) :: dom - CHARACTER(*), INTENT(IN) :: tomlName - TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile - CHARACTER(*), OPTIONAL, INTENT(IN) :: filename - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml - END SUBROUTINE bc_ImportFromToml2 -END INTERFACE AbstractBCImportFromToml - !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- @@ -362,27 +294,6 @@ MODULE SUBROUTINE bc_Get(obj, nodeNum, nodalValue, times) END SUBROUTINE bc_Get END INTERFACE -!---------------------------------------------------------------------------- -! Get@GetMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-02-12 -! summary: Get the node number and nodal value - -INTERFACE - MODULE SUBROUTINE bc_GetFEVar(obj, fevar, globalNode, & - & spaceQuadPoints, timeQuadPoints, atime, timeVec) - CLASS(AbstractBC_), INTENT(IN) :: obj - TYPE(FEVariable_), INTENT(INOUT) :: fevar - INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: spaceQuadPoints(:, :) - REAL(DFP), OPTIONAL, INTENT(IN) :: timeQuadPoints(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: atime - REAL(DFP), OPTIONAL, INTENT(IN) :: timeVec(:) - END SUBROUTINE bc_GetFEVar -END INTERFACE - !---------------------------------------------------------------------------- ! GetFromFunction@GetMethods !---------------------------------------------------------------------------- @@ -416,10 +327,10 @@ END FUNCTION bc_GetDOFNo !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_IsUseFunction(obj) RESULT(ans) + MODULE PURE FUNCTION bc_isUseFunction(obj) RESULT(ans) CLASS(AbstractBC_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION bc_IsUseFunction + END FUNCTION bc_isUseFunction END INTERFACE !---------------------------------------------------------------------------- @@ -427,20 +338,20 @@ END FUNCTION bc_IsUseFunction !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & - & timeNodalValue, spaceTimeNodalValue, spaceFunction, timeFunction, & - & spaceTimeFunction) + MODULE SUBROUTINE bc_Set(obj, ConstantNodalValue, SpaceNodalValue, & + & TimeNodalValue, SpaceTimeNodalValue, SpaceFunction, TimeFunction, & + & SpaceTimeFunction) CLASS(AbstractBC_), INTENT(INOUT) :: obj - REAL(DFP), OPTIONAL, INTENT(IN) :: constantNodalValue - REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) + REAL(DFP), OPTIONAL, INTENT(IN) :: ConstantNodalValue + REAL(DFP), OPTIONAL, INTENT(IN) :: SpaceNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: TimeNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: SpaceTimeNodalValue(:, :) PROCEDURE(iface_SpaceTimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & spaceTimeFunction + & SpaceTimeFunction PROCEDURE(iface_SpaceFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & spaceFunction + & SpaceFunction PROCEDURE(iface_TimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & timeFunction + & TimeFunction END SUBROUTINE bc_Set END INTERFACE @@ -468,19 +379,4 @@ MODULE PURE SUBROUTINE bc_GetQuery(obj, isInitiated, & END SUBROUTINE bc_GetQuery END INTERFACE -!---------------------------------------------------------------------------- -! GetPrefix@GetMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-14 -! summary: Get prefix - -INTERFACE - MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) - CLASS(AbstractBC_), INTENT(IN) :: obj - CHARACTER(:), ALLOCATABLE :: ans - END FUNCTION bc_GetPrefix -END INTERFACE - END MODULE AbstractBC_Class diff --git a/src/modules/AbstractFE/src/AbstractFE_Class.F90 b/src/modules/AbstractFE/src/AbstractFE_Class.F90 index 8f104c19b..0df6d4f3a 100644 --- a/src/modules/AbstractFE/src/AbstractFE_Class.F90 +++ b/src/modules/AbstractFE/src/AbstractFE_Class.F90 @@ -766,8 +766,7 @@ MODULE SUBROUTINE fe_GetQuadraturePoints1(obj, quad, quadratureType, & !! GaussChebyshevRadau, GaussChebyshevRadauLeft !! GaussChebyshevRadauRight INTEGER(I4B), OPTIONAL, INTENT(IN) :: order(:) - !! Order of integrand - !! either the order or the nips should be present + !! Order of integrand, either order or nips should be present !! Both nips and order should not be present INTEGER(I4B), OPTIONAL, INTENT(IN) :: nips(:) !! Number of integration points required diff --git a/src/modules/DirichletBC/src/DirichletBC_Class.F90 b/src/modules/DirichletBC/src/DirichletBC_Class.F90 index ad35bf899..4d5f424d7 100644 --- a/src/modules/DirichletBC/src/DirichletBC_Class.F90 +++ b/src/modules/DirichletBC/src/DirichletBC_Class.F90 @@ -22,8 +22,6 @@ MODULE DirichletBC_Class USE Domain_Class, ONLY: Domain_ USE FPL, ONLY: ParameterList_ USE AbstractBC_Class -USE tomlf, ONLY: toml_table -USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "DirichletBC_Class" @@ -33,7 +31,6 @@ MODULE DirichletBC_Class PUBLIC :: DirichletBCPointer_ PUBLIC :: AddDirichletBC PUBLIC :: GetDirichletBCPointer -PUBLIC :: DirichletBCImportFromToml !---------------------------------------------------------------------------- ! DirichletBC_ @@ -46,7 +43,9 @@ MODULE DirichletBC_Class TYPE, EXTENDS(AbstractBC_) :: DirichletBC_ CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & + & bc_checkEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate FINAL :: bc_Final END TYPE DirichletBC_ @@ -86,6 +85,53 @@ MODULE SUBROUTINE bc_Deallocate_Ptr_Vector(obj) END SUBROUTINE bc_Deallocate_Ptr_Vector END INTERFACE DEALLOCATE +!---------------------------------------------------------------------------- +! checkEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE bc_checkEssentialParam(obj, param) + CLASS(DirichletBC_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE bc_checkEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! setDirichletParam@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE SetDirichletBCParam(param, name, idof, nodalValueType, & + & useFunction, isNormal, isTangent) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B), INTENT(IN) :: idof + INTEGER(I4B), INTENT(IN) :: nodalValueType + !! Space + !! Time + !! SpaceTime + !! Constant + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTangent + END SUBROUTINE SetDirichletBCParam +END INTERFACE + +PUBLIC :: SetDirichletBCParam + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) + CLASS(DirichletBC_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(MeshSelection_), INTENT(IN) :: boundary + CLASS(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE bc_Initiate +END INTERFACE + !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -137,61 +183,6 @@ MODULE FUNCTION bc_GetDirichletBCPointer(dbc, dbcNo) RESULT(ans) END FUNCTION bc_GetDirichletBCPointer END INTERFACE GetDirichletBCPointer -!---------------------------------------------------------------------------- -! GetPrefix@GetMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-14 -! summary: Get the prefix - -INTERFACE - MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) - CLASS(DirichletBC_), INTENT(IN) :: obj - CHARACTER(:), ALLOCATABLE :: ans - END FUNCTION bc_GetPrefix -END INTERFACE - -!---------------------------------------------------------------------------- -! ImportFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate param from the toml file - -INTERFACE DirichletBCImportFromToml - MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom, tomlName) - TYPE(DirichletBCPointer_), INTENT(INOUT) :: obj(:) - !! Should be allocated outside - TYPE(toml_table), INTENT(INOUT) :: table - !! Toml table to returned - CLASS(Domain_), TARGET, INTENT(IN) :: dom - !! domain - CHARACTER(*), INTENT(IN) :: tomlName - END SUBROUTINE bc_ImportFromToml1 -END INTERFACE DirichletBCImportFromToml - -!---------------------------------------------------------------------------- -! ImportFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate kernel from the toml file - -INTERFACE DirichletBCImportFromToml - MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & - & filename, printToml) - TYPE(DirichletBCPointer_), INTENT(INOUT) :: obj(:) - CLASS(Domain_), TARGET, INTENT(IN) :: dom - CHARACTER(*), INTENT(IN) :: tomlName - TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile - CHARACTER(*), OPTIONAL, INTENT(IN) :: filename - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml - END SUBROUTINE bc_ImportFromToml2 -END INTERFACE DirichletBCImportFromToml - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/modules/Fhash/CMakeLists.txt b/src/modules/Fhash/CMakeLists.txt deleted file mode 100644 index 26f0a3426..000000000 --- a/src/modules/Fhash/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# This program is taken from -# https://github.com/LKedward/fhash - -SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") -TARGET_SOURCES( - ${PROJECT_NAME} PRIVATE - ${src_path}/fhash.F90 - ${src_path}/fhash_sll.F90 - ${src_path}/fhash_data_container.F90 - ${src_path}/fhash_tbl.F90 - ${src_path}/fhash_tbl_iter.F90 - ${src_path}/fhash_fnv.F90 - ${src_path}/fhash_key/base.F90 - ${src_path}/fhash_key/int32.F90 - ${src_path}/fhash_key/int64.F90 - ${src_path}/fhash_key/char.F90 - ${src_path}/fhash_key/int32_1d.F90 - ${src_path}/fhash_key/int64_1d.F90 -) diff --git a/src/modules/Fhash/src/fhash.F90 b/src/modules/Fhash/src/fhash.F90 deleted file mode 100644 index 20092465a..000000000 --- a/src/modules/Fhash/src/fhash.F90 +++ /dev/null @@ -1,14 +0,0 @@ -! fhash module is taken from -! https://github.com/LKedward/fhash - -MODULE fhash -USE fhash_tbl, ONLY: fhash_tbl_t -USE fhash_tbl_iter, ONLY: fhash_iter_t -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_key_char, ONLY: fhash_key_char_t, fhash_key -USE fhash_key_int32, ONLY: fhash_key_int32_t, fhash_key -USE fhash_key_int64, ONLY: fhash_key_int64_t, fhash_key -USE fhash_key_int32_1d, ONLY: fhash_key_int32_1d_t, fhash_key -USE fhash_key_int64_1d, ONLY: fhash_key_int64_1d_t, fhash_key -IMPLICIT NONE -END MODULE fhash diff --git a/src/modules/Fhash/src/fhash_data_container.F90 b/src/modules/Fhash/src/fhash_data_container.F90 deleted file mode 100644 index 41fdaac69..000000000 --- a/src/modules/Fhash/src/fhash_data_container.F90 +++ /dev/null @@ -1,241 +0,0 @@ -! This library is taken from -! https://github.com/LKedward/fhash -!> Implements simple container type -!> for polymorphic scalars and 1D arrays -MODULE fhash_data_container -USE ISO_FORTRAN_ENV, ONLY: sp => REAL32, dp => REAL64, INT32, INT64 -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_container_t -PUBLIC fhash_container - -!> Generic container for scalar and 1D data -TYPE fhash_container_t - - CLASS(*), ALLOCATABLE :: scalar_data - CLASS(*), POINTER :: scalar_ptr => NULL() - -CONTAINS - - PROCEDURE :: allocated => fhash_container_allocated - PROCEDURE :: get => fhash_container_get_scalar - PROCEDURE :: get_ptr => fhash_container_get_scalar_ptr - -END TYPE fhash_container_t - -!> Create a fhash_container object from a polymorphic value -INTERFACE fhash_container - MODULE PROCEDURE fhash_container_scalar -END INTERFACE fhash_container - -CONTAINS - -!> Helper to initialise a polymorphic data container with scalar -FUNCTION fhash_container_scalar(VALUE, POINTER) RESULT(container) - - !> Value to store - CLASS(*), INTENT(in), TARGET :: VALUE - - !> If .true., store pointer to value instead of copying - LOGICAL, INTENT(in), OPTIONAL :: POINTER - - TYPE(fhash_container_t) :: container - - IF (PRESENT(POINTER)) THEN - IF (POINTER) THEN - container%scalar_ptr => VALUE - ELSE - IF (ALLOCATED(container%scalar_data)) DEALLOCATE (container%scalar_data) - ALLOCATE (container%scalar_data, source=VALUE) - END IF - ELSE - IF (ALLOCATED(container%scalar_data)) DEALLOCATE (container%scalar_data) - ALLOCATE (container%scalar_data, source=VALUE) - END IF - -END FUNCTION fhash_container_scalar - -!> Helper to determine if container contains anything -FUNCTION fhash_container_allocated(container) RESULT(alloc) - CLASS(fhash_container_t), INTENT(in) :: container - LOGICAL :: alloc - - alloc = ALLOCATED(container%scalar_data) .OR. & - ASSOCIATED(container%scalar_ptr) - -END FUNCTION fhash_container_allocated - -!> Helper to return container value as intrinsic type - subroutine fhash_container_get_scalar(container,i32,i64,r32,r64,char,bool,raw,match,type_string) - CLASS(fhash_container_t), INTENT(in), TARGET :: container - INTEGER(INT32), INTENT(out), OPTIONAL :: i32 - INTEGER(INT64), INTENT(out), OPTIONAL :: i64 - REAL(sp), INTENT(out), OPTIONAL :: r32 - REAL(dp), INTENT(out), OPTIONAL :: r64 - CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: char - LOGICAL, INTENT(out), OPTIONAL :: bool - CLASS(*), ALLOCATABLE, INTENT(out), OPTIONAL :: raw - LOGICAL, INTENT(out), OPTIONAL :: match - CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: type_string - - CLASS(*), POINTER :: DATA - - IF (PRESENT(match)) match = .FALSE. - - IF (.NOT. container%ALLOCATED()) RETURN - - IF (ALLOCATED(container%scalar_data)) THEN - DATA => container%scalar_data - ELSE - DATA => container%scalar_ptr - END IF - - IF (PRESENT(raw)) THEN - IF (PRESENT(match)) match = .TRUE. - ALLOCATE (raw, source=DATA) - END IF - - SELECT TYPE (d => DATA) - TYPE is (INTEGER(INT32)) - IF (PRESENT(type_string)) type_string = 'integer32' - IF (PRESENT(i32)) THEN - IF (PRESENT(match)) match = .TRUE. - i32 = d - RETURN - END IF - - TYPE is (INTEGER(INT64)) - IF (PRESENT(type_string)) type_string = 'integer64' - IF (PRESENT(i64)) THEN - IF (PRESENT(match)) match = .TRUE. - i64 = d - RETURN - END IF - - TYPE is (REAL(sp)) - IF (PRESENT(type_string)) type_string = 'real32' - IF (PRESENT(r32)) THEN - IF (PRESENT(match)) match = .TRUE. - r32 = d - RETURN - END IF - - TYPE is (REAL(dp)) - IF (PRESENT(type_string)) type_string = 'real64' - IF (PRESENT(r64)) THEN - IF (PRESENT(match)) match = .TRUE. - r64 = d - RETURN - END IF - - TYPE is (CHARACTER(*)) - IF (PRESENT(type_string)) type_string = 'character*' - IF (PRESENT(char)) THEN - IF (PRESENT(match)) match = .TRUE. - char = d - RETURN - END IF - - TYPE is (LOGICAL) - IF (PRESENT(type_string)) type_string = 'logical' - IF (PRESENT(bool)) THEN - IF (PRESENT(match)) match = .TRUE. - bool = d - RETURN - END IF - - CLASS default - IF (PRESENT(type_string)) type_string = 'unknown' - - END SELECT - -END SUBROUTINE fhash_container_get_scalar - -!> Helper to return pointer to container value as intrinsic type - subroutine fhash_container_get_scalar_ptr(container,i32,i64,r32,r64,char,bool,raw,match,type_string) - CLASS(fhash_container_t), INTENT(in), TARGET :: container - INTEGER(INT32), POINTER, INTENT(out), OPTIONAL :: i32 - INTEGER(INT64), POINTER, INTENT(out), OPTIONAL :: i64 - REAL(sp), POINTER, INTENT(out), OPTIONAL :: r32 - REAL(dp), POINTER, INTENT(out), OPTIONAL :: r64 - CHARACTER(:), POINTER, INTENT(out), OPTIONAL :: char - LOGICAL, POINTER, INTENT(out), OPTIONAL :: bool - CLASS(*), POINTER, INTENT(out), OPTIONAL :: raw - LOGICAL, INTENT(out), OPTIONAL :: match - CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: type_string - - CLASS(*), POINTER :: DATA - - IF (PRESENT(match)) match = .FALSE. - - IF (.NOT. container%ALLOCATED()) RETURN - - IF (ALLOCATED(container%scalar_data)) THEN - DATA => container%scalar_data - ELSE - DATA => container%scalar_ptr - END IF - - IF (PRESENT(raw)) THEN - IF (PRESENT(match)) match = .TRUE. - raw => DATA - END IF - - SELECT TYPE (d => DATA) - TYPE is (INTEGER(INT32)) - IF (PRESENT(i32)) THEN - IF (PRESENT(match)) match = .TRUE. - IF (PRESENT(type_string)) type_string = 'integer32' - i32 => d - RETURN - END IF - - TYPE is (INTEGER(INT64)) - IF (PRESENT(i64)) THEN - IF (PRESENT(match)) match = .TRUE. - IF (PRESENT(type_string)) type_string = 'integer64' - i64 => d - RETURN - END IF - - TYPE is (REAL(sp)) - IF (PRESENT(r32)) THEN - IF (PRESENT(match)) match = .TRUE. - IF (PRESENT(type_string)) type_string = 'real32' - r32 => d - RETURN - END IF - - TYPE is (REAL(dp)) - IF (PRESENT(r64)) THEN - IF (PRESENT(match)) match = .TRUE. - IF (PRESENT(type_string)) type_string = 'real64' - r64 => d - RETURN - END IF - - TYPE is (CHARACTER(*)) - IF (PRESENT(char)) THEN - IF (PRESENT(match)) match = .TRUE. - IF (PRESENT(type_string)) type_string = 'character*' - char => d - RETURN - END IF - - TYPE is (LOGICAL) - IF (PRESENT(bool)) THEN - IF (PRESENT(match)) match = .TRUE. - IF (PRESENT(type_string)) type_string = 'logical' - bool => d - RETURN - END IF - - CLASS DEFAULT - IF (PRESENT(type_string)) type_string = 'unknown' - - END SELECT - -END SUBROUTINE fhash_container_get_scalar_ptr - -END MODULE fhash_data_container diff --git a/src/modules/Fhash/src/fhash_fnv.F90 b/src/modules/Fhash/src/fhash_fnv.F90 deleted file mode 100644 index 1bd04b5b7..000000000 --- a/src/modules/Fhash/src/fhash_fnv.F90 +++ /dev/null @@ -1,181 +0,0 @@ -!> A module for Fowler–Noll–Vo (FNV) hashing -!> -!> Implements the FNV 1a algorithm for 32bit hashes -!> -!> Supports hashing of: -!> - 32bit integers (scalar & 1D array) -!> - 64bit integers (scalar & 1D array) -!> - character(*), default kind -!> -!> The lack of unsigned arithmetic in Fortran means that -!> 64bit arithmetic is needed to perform 32bit hashing. -!> Hashes are therefore returned as int64. -!> -MODULE fhash_fnv -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 -USE ISO_C_BINDING, ONLY: C_CHAR -IMPLICIT NONE - -PRIVATE -PUBLIC :: fnv_1a, hash_string - -!> Starting seed -INTEGER(INT64), PARAMETER :: FNV_OFFSET_32 = 2166136261_INT64 - -!> Hashing prime -INTEGER(INT64), PARAMETER :: FNV_PRIME_32 = 16777619_INT64 - -!> Generic interface to perform hashing -!> -!> Usage: -!>```fortran -!> fnv_1a([seed],input) -!>``` -!> where `input` is any of the supported types -INTERFACE fnv_1a - MODULE PROCEDURE fnv_1a_char_scalar - MODULE PROCEDURE fnv_1a_char_scalar_seed - MODULE PROCEDURE fnv_1a_int32_scalar - MODULE PROCEDURE fnv_1a_int32_scalar_seed - MODULE PROCEDURE fnv_1a_int32_1d - MODULE PROCEDURE fnv_1a_int32_1d_seed - MODULE PROCEDURE fnv_1a_int64_scalar - MODULE PROCEDURE fnv_1a_int64_scalar_seed - MODULE PROCEDURE fnv_1a_int64_1d - MODULE PROCEDURE fnv_1a_int64_1d_seed -END INTERFACE fnv_1a - -CONTAINS - -!> Hash a single default kind character variable -PURE FUNCTION fnv_1a_char_scalar(input) RESULT(hash) - CHARACTER(*), INTENT(in) :: input - INTEGER(INT64) :: hash - - hash = fnv_1a(FNV_OFFSET_32, input) - -END FUNCTION fnv_1a_char_scalar - -!> Hash a character(*) string of default kind -PURE FUNCTION fnv_1a_char_scalar_seed(seed, input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: seed - CHARACTER(*), INTENT(in) :: input - INTEGER(INT64) :: hash - - INTEGER :: i - INTEGER(INT64) :: item - - hash = seed - - DO i = 1, LEN(input) - item = TRANSFER([IACHAR(input(i:i), INT32), 0_INT32], item) - hash = IEOR(hash, item) * fnv_prime_32 - END DO - -END FUNCTION fnv_1a_char_scalar_seed - -!> Hash a single 32bit integer -PURE FUNCTION fnv_1a_int32_scalar(input) RESULT(hash) - INTEGER(INT32), INTENT(in) :: input - INTEGER(INT64) :: hash - - hash = fnv_1a(FNV_OFFSET_32, input) - -END FUNCTION fnv_1a_int32_scalar - -!> Hash a single 32bit integer with a starting seed -PURE FUNCTION fnv_1a_int32_scalar_seed(seed, input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: seed - INTEGER(INT32), INTENT(in) :: input - INTEGER(INT64) :: hash - - CHARACTER(len=4, kind=C_CHAR) :: chars - - chars = TRANSFER(input, chars) - - hash = fnv_1a(seed, chars) - -END FUNCTION fnv_1a_int32_scalar_seed - -!> Hash a 1D array of 32bit integers -PURE FUNCTION fnv_1a_int32_1d(input) RESULT(hash) - INTEGER(INT32), INTENT(in) :: input(:) - INTEGER(INT64) :: hash - - hash = fnv_1a(FNV_OFFSET_32, input) - -END FUNCTION fnv_1a_int32_1d - -!> Hash a 1D array of 32bit integers with a starting seed -PURE FUNCTION fnv_1a_int32_1d_seed(seed, input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: seed - INTEGER(INT32), INTENT(in) :: input(:) - INTEGER(INT64) :: hash - - INTEGER :: i - - hash = seed - DO i = 1, SIZE(input) - hash = fnv_1a(hash, input(i)) - END DO - -END FUNCTION fnv_1a_int32_1d_seed - -!> Hash a single 64bit integer -PURE FUNCTION fnv_1a_int64_scalar(input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: input - INTEGER(INT64) :: hash - - hash = fnv_1a(FNV_OFFSET_32, input) - -END FUNCTION fnv_1a_int64_scalar - -!> Hash a single 64bit integer with a starting seed -PURE FUNCTION fnv_1a_int64_scalar_seed(seed, input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: seed - INTEGER(INT64), INTENT(in) :: input - INTEGER(INT64) :: hash - - CHARACTER(len=8, kind=C_CHAR) :: chars - - chars = TRANSFER(input, chars) - - hash = fnv_1a(seed, chars) - -END FUNCTION fnv_1a_int64_scalar_seed - -!> Hash a 1D array of 64bit integers -PURE FUNCTION fnv_1a_int64_1d(input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: input(:) - INTEGER(INT64) :: hash - - hash = fnv_1a(FNV_OFFSET_32, input) - -END FUNCTION fnv_1a_int64_1d - -!> Hash a 1D array of 64bit integers with a starting seed -PURE FUNCTION fnv_1a_int64_1d_seed(seed, input) RESULT(hash) - INTEGER(INT64), INTENT(in) :: seed - INTEGER(INT64), INTENT(in) :: input(:) - INTEGER(INT64) :: hash - - INTEGER :: i - - hash = seed - DO i = 1, SIZE(input) - hash = fnv_1a(hash, input(i)) - END DO - -END FUNCTION fnv_1a_int64_1d_seed - -!> Help fcn to convert hash to hex representation -FUNCTION hash_string(hash_value) RESULT(str) - INTEGER(INT64), INTENT(in) :: hash_value - CHARACTER(:), ALLOCATABLE :: str - - ALLOCATE (CHARACTER(len=10) :: str) - WRITE (str, '(Z0)') INT(hash_value, INT32) - -END FUNCTION hash_string - -END MODULE fhash_fnv diff --git a/src/modules/Fhash/src/fhash_key/base.F90 b/src/modules/Fhash/src/fhash_key/base.F90 deleted file mode 100644 index e7537bdec..000000000 --- a/src/modules/Fhash/src/fhash_key/base.F90 +++ /dev/null @@ -1,42 +0,0 @@ -!> Implements an abstract type for hash keys -!> -MODULE fhash_key_base -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_key_t - -!> Abstract base type for defining hash keys -TYPE, ABSTRACT :: fhash_key_t -CONTAINS - PROCEDURE(hash_proc), DEFERRED :: hash - PROCEDURE(equality_proc), DEFERRED :: equals - PROCEDURE(to_string_proc), DEFERRED :: to_string - GENERIC, PUBLIC :: OPERATOR(==) => equals -END TYPE fhash_key_t - -ABSTRACT INTERFACE - - PURE FUNCTION equality_proc(key1, key2) RESULT(keys_equal) - IMPORT - CLASS(fhash_key_t), INTENT(in) :: key1 - CLASS(fhash_key_t), INTENT(in) :: key2 - LOGICAL :: keys_equal - END FUNCTION equality_proc - - PURE FUNCTION hash_proc(key) RESULT(hash) - IMPORT - CLASS(fhash_key_t), INTENT(in) :: key - INTEGER(INT64) :: hash - END FUNCTION hash_proc - - FUNCTION to_string_proc(key) RESULT(str) - IMPORT - CLASS(fhash_key_t), INTENT(in) :: key - CHARACTER(:), ALLOCATABLE :: str - END FUNCTION to_string_proc - -END INTERFACE - -END MODULE fhash_key_base diff --git a/src/modules/Fhash/src/fhash_key/char.F90 b/src/modules/Fhash/src/fhash_key/char.F90 deleted file mode 100644 index 63f1a90e9..000000000 --- a/src/modules/Fhash/src/fhash_key/char.F90 +++ /dev/null @@ -1,76 +0,0 @@ -!> Implements a concrete type for scalar int32 hash keys -!> -MODULE fhash_key_char -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_fnv, ONLY: fnv_1a -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_key_char_t -PUBLIC fhash_key - -!> Hash table key container -TYPE, EXTENDS(fhash_key_t) :: fhash_key_char_t - PRIVATE - CHARACTER(:), ALLOCATABLE :: VALUE -CONTAINS - PROCEDURE, PASS :: hash => key_hash_char - PROCEDURE, PASS :: equals => key_equal_char - PROCEDURE, PASS :: to_string => key_char_to_string -END TYPE fhash_key_char_t - -INTERFACE fhash_key - MODULE PROCEDURE :: key_from_char -END INTERFACE fhash_key - -CONTAINS - -!> Check if two keys are equal -PURE FUNCTION key_equal_char(key1, key2) RESULT(keys_equal) - CLASS(fhash_key_char_t), INTENT(in) :: key1 - CLASS(fhash_key_t), INTENT(in) :: key2 - LOGICAL :: keys_equal - - keys_equal = .FALSE. - - SELECT TYPE (k2 => key2) - TYPE is (fhash_key_char_t) - IF (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE)) THEN - IF (key1%VALUE == k2%VALUE) THEN - keys_equal = .TRUE. - RETURN - END IF - END IF - END SELECT - -END FUNCTION key_equal_char - -!> Generate hash of key -PURE FUNCTION key_hash_char(key) RESULT(hash) - CLASS(fhash_key_char_t), INTENT(in) :: key - INTEGER(INT64) :: hash - - hash = fnv_1a(key%VALUE) - -END FUNCTION key_hash_char - -!> Generate string representation of hash -FUNCTION key_char_to_string(key) RESULT(str) - CLASS(fhash_key_char_t), INTENT(in) :: key - CHARACTER(:), ALLOCATABLE :: str - - str = key%VALUE - -END FUNCTION key_char_to_string - -!> Create new key container from a scalar int32 -FUNCTION key_from_char(source) RESULT(key) - CHARACTER(*), INTENT(in) :: source - TYPE(fhash_key_char_t) :: key - - key%VALUE = source - -END FUNCTION key_from_char - -END MODULE fhash_key_char diff --git a/src/modules/Fhash/src/fhash_key/int32.F90 b/src/modules/Fhash/src/fhash_key/int32.F90 deleted file mode 100644 index 0d3fac8e2..000000000 --- a/src/modules/Fhash/src/fhash_key/int32.F90 +++ /dev/null @@ -1,76 +0,0 @@ -!> Implements a concrete type for scalar int32 hash keys -!> -MODULE fhash_key_int32 -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_fnv, ONLY: fnv_1a -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_key_int32_t -PUBLIC fhash_key - -!> Hash table key container -TYPE, EXTENDS(fhash_key_t) :: fhash_key_int32_t - PRIVATE - INTEGER(INT32) :: VALUE -CONTAINS - PROCEDURE, PASS :: hash => key_hash_int32 - PROCEDURE, PASS :: equals => key_equal_int32 - PROCEDURE, PASS :: to_string => key_int32_to_string -END TYPE fhash_key_int32_t - -INTERFACE fhash_key - MODULE PROCEDURE :: key_from_int32 -END INTERFACE fhash_key - -CONTAINS - -!> Check if two keys are equal -PURE FUNCTION key_equal_int32(key1, key2) RESULT(keys_equal) - CLASS(fhash_key_int32_t), INTENT(in) :: key1 - CLASS(fhash_key_t), INTENT(in) :: key2 - LOGICAL :: keys_equal - - keys_equal = .FALSE. - - SELECT TYPE (k2 => key2) - TYPE is (fhash_key_int32_t) - IF (key1%VALUE == k2%VALUE) THEN - keys_equal = .TRUE. - RETURN - END IF - END SELECT - -END FUNCTION key_equal_int32 - -!> Generate hash of key -PURE FUNCTION key_hash_int32(key) RESULT(hash) - CLASS(fhash_key_int32_t), INTENT(in) :: key - INTEGER(INT64) :: hash - - hash = fnv_1a(key%VALUE) - -END FUNCTION key_hash_int32 - -!> Generate string representation of hash -PURE FUNCTION key_int32_to_string(key) RESULT(str) - CLASS(fhash_key_int32_t), INTENT(in) :: key - CHARACTER(:), ALLOCATABLE :: str - - ALLOCATE (CHARACTER(1024) :: str) - WRITE (str, *) key%VALUE - str = TRIM(str) - -END FUNCTION key_int32_to_string - -!> Create new key container from a scalar int32 -FUNCTION key_from_int32(source) RESULT(key) - INTEGER(INT32), INTENT(in) :: source - TYPE(fhash_key_int32_t) :: key - - key%VALUE = source - -END FUNCTION key_from_int32 - -END MODULE fhash_key_int32 diff --git a/src/modules/Fhash/src/fhash_key/int32_1d.F90 b/src/modules/Fhash/src/fhash_key/int32_1d.F90 deleted file mode 100644 index 78c0123e5..000000000 --- a/src/modules/Fhash/src/fhash_key/int32_1d.F90 +++ /dev/null @@ -1,82 +0,0 @@ -!> Implements a concrete type for 1D int32 array hash keys -!> -MODULE fhash_key_int32_1d -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_fnv, ONLY: fnv_1a -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_key_int32_1d_t -PUBLIC fhash_key - -!> Hash table key container -TYPE, EXTENDS(fhash_key_t) :: fhash_key_int32_1d_t - PRIVATE - INTEGER(INT32), ALLOCATABLE :: VALUE(:) -CONTAINS - PROCEDURE, PASS :: hash => key_hash_int32_1d - PROCEDURE, PASS :: equals => key_equal_int32_1d - PROCEDURE, PASS :: to_string => key_int32_1d_to_string -END TYPE fhash_key_int32_1d_t - -INTERFACE fhash_key - MODULE PROCEDURE :: key_from_int32_1d -END INTERFACE fhash_key - -CONTAINS - -!> Check if two keys are equal -PURE FUNCTION key_equal_int32_1d(key1, key2) RESULT(keys_equal) - CLASS(fhash_key_int32_1d_t), INTENT(in) :: key1 - CLASS(fhash_key_t), INTENT(in) :: key2 - LOGICAL :: keys_equal - - keys_equal = .FALSE. - - SELECT TYPE (k2 => key2) - TYPE is (fhash_key_int32_1d_t) - IF (.NOT. (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE))) THEN - RETURN - END IF - IF (SIZE(key1%VALUE) /= SIZE(k2%VALUE)) THEN - RETURN - END IF - IF (ALL(key1%VALUE == k2%VALUE)) THEN - keys_equal = .TRUE. - RETURN - END IF - END SELECT - -END FUNCTION key_equal_int32_1d - -!> Generate hash of key -PURE FUNCTION key_hash_int32_1d(key) RESULT(hash) - CLASS(fhash_key_int32_1d_t), INTENT(in) :: key - INTEGER(INT64) :: hash - - hash = fnv_1a(key%VALUE) - -END FUNCTION key_hash_int32_1d - -!> Generate string representation of hash -PURE FUNCTION key_int32_1d_to_string(key) RESULT(str) - CLASS(fhash_key_int32_1d_t), INTENT(in) :: key - CHARACTER(:), ALLOCATABLE :: str - - ALLOCATE (CHARACTER(1024) :: str) - WRITE (str, *) key%VALUE - str = TRIM(str) - -END FUNCTION key_int32_1d_to_string - -!> Create new key container from a scalar int32 -FUNCTION key_from_int32_1d(source) RESULT(key) - INTEGER(INT32), INTENT(in) :: source(:) - TYPE(fhash_key_int32_1d_t) :: key - - key%VALUE = source - -END FUNCTION key_from_int32_1d - -END MODULE fhash_key_int32_1d diff --git a/src/modules/Fhash/src/fhash_key/int64.F90 b/src/modules/Fhash/src/fhash_key/int64.F90 deleted file mode 100644 index a4b5e18d2..000000000 --- a/src/modules/Fhash/src/fhash_key/int64.F90 +++ /dev/null @@ -1,76 +0,0 @@ -!> Implements a concrete type for scalar int64 hash keys -!> -MODULE fhash_key_int64 -USE ISO_FORTRAN_ENV, ONLY: INT64 -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_fnv, ONLY: fnv_1a -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_key_int64_t -PUBLIC fhash_key - -!> Hash table key container -TYPE, EXTENDS(fhash_key_t) :: fhash_key_int64_t - PRIVATE - INTEGER(INT64) :: VALUE -CONTAINS - PROCEDURE, PASS :: hash => key_hash_int64 - PROCEDURE, PASS :: equals => key_equal_int64 - PROCEDURE, PASS :: to_string => key_int64_to_string -END TYPE fhash_key_int64_t - -INTERFACE fhash_key - MODULE PROCEDURE :: key_from_int64 -END INTERFACE fhash_key - -CONTAINS - -!> Check if two keys are equal -PURE FUNCTION key_equal_int64(key1, key2) RESULT(keys_equal) - CLASS(fhash_key_int64_t), INTENT(in) :: key1 - CLASS(fhash_key_t), INTENT(in) :: key2 - LOGICAL :: keys_equal - - keys_equal = .FALSE. - - SELECT TYPE (k2 => key2) - TYPE is (fhash_key_int64_t) - IF (key1%VALUE == k2%VALUE) THEN - keys_equal = .TRUE. - RETURN - END IF - END SELECT - -END FUNCTION key_equal_int64 - -!> Generate hash of key -PURE FUNCTION key_hash_int64(key) RESULT(hash) - CLASS(fhash_key_int64_t), INTENT(in) :: key - INTEGER(INT64) :: hash - - hash = fnv_1a(key%VALUE) - -END FUNCTION key_hash_int64 - -!> Generate string representation of hash -PURE FUNCTION key_int64_to_string(key) RESULT(str) - CLASS(fhash_key_int64_t), INTENT(in) :: key - CHARACTER(:), ALLOCATABLE :: str - - ALLOCATE (CHARACTER(1024) :: str) - WRITE (str, *) key%VALUE - str = TRIM(str) - -END FUNCTION key_int64_to_string - -!> Create new key container from a scalar int64 -FUNCTION key_from_int64(source) RESULT(key) - INTEGER(INT64), INTENT(in) :: source - TYPE(fhash_key_int64_t) :: key - - key%VALUE = source - -END FUNCTION key_from_int64 - -END MODULE fhash_key_int64 diff --git a/src/modules/Fhash/src/fhash_key/int64_1d.F90 b/src/modules/Fhash/src/fhash_key/int64_1d.F90 deleted file mode 100644 index 2c2c2ccd8..000000000 --- a/src/modules/Fhash/src/fhash_key/int64_1d.F90 +++ /dev/null @@ -1,82 +0,0 @@ -!> Implements a concrete type for 1D int64 array hash keys -!> -MODULE fhash_key_int64_1d -USE ISO_FORTRAN_ENV, ONLY: INT64 -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_fnv, ONLY: fnv_1a -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_key_int64_1d_t -PUBLIC fhash_key - -!> Hash table key container -TYPE, EXTENDS(fhash_key_t) :: fhash_key_int64_1d_t - PRIVATE - INTEGER(INT64), ALLOCATABLE :: VALUE(:) -CONTAINS - PROCEDURE, PASS :: hash => key_hash_int64_1d - PROCEDURE, PASS :: equals => key_equal_int64_1d - PROCEDURE, PASS :: to_string => key_int64_1d_to_string -END TYPE fhash_key_int64_1d_t - -INTERFACE fhash_key - MODULE PROCEDURE :: key_from_int64_1d -END INTERFACE fhash_key - -CONTAINS - -!> Check if two keys are equal -PURE FUNCTION key_equal_int64_1d(key1, key2) RESULT(keys_equal) - CLASS(fhash_key_int64_1d_t), INTENT(in) :: key1 - CLASS(fhash_key_t), INTENT(in) :: key2 - LOGICAL :: keys_equal - - keys_equal = .FALSE. - - SELECT TYPE (k2 => key2) - TYPE is (fhash_key_int64_1d_t) - IF (.NOT. (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE))) THEN - RETURN - END IF - IF (SIZE(key1%VALUE) /= SIZE(k2%VALUE)) THEN - RETURN - END IF - IF (ALL(key1%VALUE == k2%VALUE)) THEN - keys_equal = .TRUE. - RETURN - END IF - END SELECT - -END FUNCTION key_equal_int64_1d - -!> Generate hash of key -PURE FUNCTION key_hash_int64_1d(key) RESULT(hash) - CLASS(fhash_key_int64_1d_t), INTENT(in) :: key - INTEGER(INT64) :: hash - - hash = fnv_1a(key%VALUE) - -END FUNCTION key_hash_int64_1d - -!> Generate string representation of hash -PURE FUNCTION key_int64_1d_to_string(key) RESULT(str) - CLASS(fhash_key_int64_1d_t), INTENT(in) :: key - CHARACTER(:), ALLOCATABLE :: str - - ALLOCATE (CHARACTER(1024) :: str) - WRITE (str, *) key%VALUE - str = TRIM(str) - -END FUNCTION key_int64_1d_to_string - -!> Create new key container from a scalar int64 -FUNCTION key_from_int64_1d(source) RESULT(key) - INTEGER(INT64), INTENT(in) :: source(:) - TYPE(fhash_key_int64_1d_t) :: key - - key%VALUE = source - -END FUNCTION key_from_int64_1d - -END MODULE fhash_key_int64_1d diff --git a/src/modules/Fhash/src/fhash_sll.F90 b/src/modules/Fhash/src/fhash_sll.F90 deleted file mode 100644 index c9aec1190..000000000 --- a/src/modules/Fhash/src/fhash_sll.F90 +++ /dev/null @@ -1,277 +0,0 @@ -!> Implements singly-linked list (sll) node with generic data container -!> -MODULE fhash_sll -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_data_container, ONLY: fhash_container_t -IMPLICIT NONE - -!> Node type for hash table singly linked list -TYPE fhash_node_t - - CLASS(fhash_key_t), ALLOCATABLE :: key - TYPE(fhash_container_t) :: VALUE - TYPE(fhash_node_t), POINTER :: next => NULL() - -END TYPE fhash_node_t - -CONTAINS - -!> Append node to SLL -RECURSIVE SUBROUTINE sll_push_node(node, key, VALUE, POINTER) - - !> Node to which to add data - TYPE(fhash_node_t), INTENT(inout) :: node - - !> Key to add - CLASS(fhash_key_t), INTENT(in) :: key - - !> Value to add - CLASS(*), INTENT(in), TARGET :: VALUE - - !> Store only a point if .true. - LOGICAL, INTENT(in), OPTIONAL :: POINTER - - IF (ALLOCATED(node%key)) THEN - - IF (node%key == key) THEN - - CALL sll_node_set(node, VALUE, POINTER) - RETURN - - END IF - - IF (.NOT. ASSOCIATED(node%next)) THEN - ALLOCATE (node%next) - END IF - - CALL sll_push_node(node%next, key, VALUE, POINTER) - - ELSE - - node%key = key - CALL sll_node_set(node, VALUE, POINTER) - - END IF - -END SUBROUTINE sll_push_node - -!> Set container value in node -!> -SUBROUTINE sll_node_set(node, VALUE, POINTER) - - !> Node to which to add data - TYPE(fhash_node_t), INTENT(inout) :: node - - !> Value to set - CLASS(*), INTENT(in), TARGET :: VALUE - - !> Store only a pointer if .true. - LOGICAL, INTENT(in), OPTIONAL :: POINTER - - IF (PRESENT(POINTER)) THEN - IF (POINTER) THEN - node%VALUE%scalar_ptr => VALUE - RETURN - END IF - END IF - - IF (ALLOCATED(node%VALUE%scalar_data)) DEALLOCATE (node%VALUE%scalar_data) - ALLOCATE (node%VALUE%scalar_data, source=VALUE) - -END SUBROUTINE sll_node_set - -!> Search for a node with a specific key. -!> Returns a pointer to the 'data' component of the corresponding node. -!> Pointer is not associated if node cannot be found -RECURSIVE SUBROUTINE sll_find_in(node, key, DATA, found) - - !> Node to search in - TYPE(fhash_node_t), INTENT(in), TARGET :: node - - !> Key to look for - CLASS(fhash_key_t) :: key - - !> Pointer to value container if found. - !> (Unassociated if the key is not found in node) - TYPE(fhash_container_t), POINTER, INTENT(out) :: DATA - - LOGICAL, INTENT(out), OPTIONAL :: found - - DATA => NULL() - - IF (PRESENT(found)) found = .FALSE. - - IF (.NOT. ALLOCATED(node%key)) THEN - - RETURN - - ELSE IF (node%key == key) THEN - - IF (PRESENT(found)) found = .TRUE. - DATA => node%VALUE - RETURN - - ELSE IF (ASSOCIATED(node%next)) THEN - - CALL sll_find_in(node%next, key, DATA, found) - - END IF - -END SUBROUTINE sll_find_in - -!> Return a node at a specific depth in the sll -RECURSIVE SUBROUTINE sll_get_at(node, depth, key, DATA, found) - - !> Node to search in - TYPE(fhash_node_t), INTENT(in), TARGET :: node - - !> Node depth to access - INTEGER, INTENT(in) :: depth - - !> Key of found item - !> (Unallocated if no node is found at specified depth) - CLASS(fhash_key_t), INTENT(out), ALLOCATABLE :: key - - !> Pointer to value container if found. - !> (Unassociated if no node is found at specified depth) - TYPE(fhash_container_t), POINTER, INTENT(out) :: DATA - - LOGICAL, INTENT(out), OPTIONAL :: found - - DATA => NULL() - - IF (PRESENT(found)) found = .FALSE. - - IF (.NOT. ALLOCATED(node%key)) THEN - - RETURN - - ELSE IF (depth == 1) THEN - - IF (PRESENT(found)) found = .TRUE. - key = node%key - DATA => node%VALUE - RETURN - - ELSE IF (ASSOCIATED(node%next)) THEN - - CALL sll_get_at(node%next, depth - 1, key, DATA, found) - - END IF - -END SUBROUTINE sll_get_at - -!> Search for a node with a specific key and remove -RECURSIVE SUBROUTINE sll_remove(node, key, found, parent_node) - - !> Node to remove from - TYPE(fhash_node_t), INTENT(inout) :: node - - !> Key to remove - CLASS(fhash_key_t) :: key - - !> Indicates if the key was found in node and removed - LOGICAL, OPTIONAL, INTENT(out) :: found - - !> Used internally - TYPE(fhash_node_t), INTENT(inout), OPTIONAL :: parent_node - - TYPE(fhash_node_t), POINTER :: next_temp - - IF (PRESENT(found)) THEN - found = .FALSE. - END IF - - IF (.NOT. ALLOCATED(node%key)) THEN - - RETURN - - ELSE IF (node%key == key) THEN - - IF (PRESENT(found)) THEN - found = .TRUE. - END IF - - IF (.NOT. PRESENT(parent_node)) THEN - ! This is the top-level node - IF (ASSOCIATED(node%next)) THEN - ! Replace with next - next_temp => node%next - node = next_temp - DEALLOCATE (next_temp) - RETURN - ELSE - ! No children, just deallocate - DEALLOCATE (node%key) - RETURN - END IF - - ELSE - ! Not top-level node - IF (ASSOCIATED(node%next)) THEN - ! Join previous with next - next_temp => node%next - DEALLOCATE (parent_node%next) - parent_node%next => next_temp - RETURN - ELSE - ! No children, just deallocate - DEALLOCATE (node%key) - DEALLOCATE (parent_node%next) - RETURN - END IF - END IF - - ELSE IF (ASSOCIATED(node%next)) THEN - ! Look further down - CALL sll_remove(node%next, key, found, node) - - END IF - -END SUBROUTINE sll_remove - -!> Deallocate node components and those of its children -RECURSIVE SUBROUTINE sll_clean(node) - - !> Node to search in - TYPE(fhash_node_t), INTENT(inout) :: node - - IF (ASSOCIATED(node%next)) THEN - - CALL sll_clean(node%next) - DEALLOCATE (node%next) - - END IF - -END SUBROUTINE sll_clean - -!> Determine depth of SLL -FUNCTION node_depth(node) RESULT(depth) - - !> Node to check depth - TYPE(fhash_node_t), INTENT(in), TARGET :: node - - INTEGER :: depth - - TYPE(fhash_node_t), POINTER :: current - - IF (.NOT. ALLOCATED(node%key)) THEN - - depth = 0 - RETURN - - ELSE - - depth = 1 - current => node - DO WHILE (ASSOCIATED(current%next)) - depth = depth + 1 - current => current%next - END DO - - END IF - -END FUNCTION node_depth - -END MODULE fhash_sll diff --git a/src/modules/Fhash/src/fhash_tbl.F90 b/src/modules/Fhash/src/fhash_tbl.F90 deleted file mode 100644 index a56527ac8..000000000 --- a/src/modules/Fhash/src/fhash_tbl.F90 +++ /dev/null @@ -1,571 +0,0 @@ -MODULE fhash_tbl -USE ISO_FORTRAN_ENV, ONLY: INT32, INT64, sp => REAL32, dp => REAL64 -USE fhash_data_container, ONLY: fhash_container -USE fhash_sll -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_tbl_t - -!> This condition should be unreachable by the public interface -INTEGER, PARAMETER, PUBLIC :: FHASH_INTERNAL_ERROR = -4 - -!> Error flag for operating on an unallocated table -INTEGER, PARAMETER, PUBLIC :: FHASH_EMPTY_TABLE = -3 - -!> Error flag for when retrieved data-type does not -!> match that expected by the invoked getter function -!> (`get_int32`,`get_int63`,`get_float`,'get_double`,`get_char`) -INTEGER, PARAMETER, PUBLIC :: FHASH_FOUND_WRONG_TYPE = -2 - -!> Error flag for when specified key is not found in the hash table -INTEGER, PARAMETER, PUBLIC :: FHASH_KEY_NOT_FOUND = -1 - -!> Default allocation size -INTEGER, PARAMETER :: FHASH_DEFAULT_ALLOCATION = 127 - -TYPE fhash_tbl_t - - TYPE(fhash_node_t), ALLOCATABLE :: buckets(:) - -CONTAINS - - PROCEDURE :: ALLOCATE => fhash_tbl_allocate - PROCEDURE :: unset => fhash_tbl_unset - PROCEDURE :: check_key => fhash_tbl_check_key - PROCEDURE :: stats => fhash_tbl_stats - - PROCEDURE :: fhash_tbl_set_scalar - GENERIC :: set => fhash_tbl_set_scalar - - PROCEDURE :: fhash_tbl_set_scalar_ptr - GENERIC :: set_ptr => fhash_tbl_set_scalar_ptr - - PROCEDURE :: fhash_tbl_get_int32, fhash_tbl_get_int64 - PROCEDURE :: fhash_tbl_get_float, fhash_tbl_get_double - PROCEDURE :: fhash_tbl_get_char, fhash_tbl_get_logical - PROCEDURE :: fhash_tbl_get_data, fhash_tbl_get_raw - - GENERIC :: get => fhash_tbl_get_int32, fhash_tbl_get_int64 - GENERIC :: get => fhash_tbl_get_float, fhash_tbl_get_double - GENERIC :: get => fhash_tbl_get_char, fhash_tbl_get_logical - GENERIC :: get => fhash_tbl_get_data - GENERIC :: get_raw => fhash_tbl_get_raw - - PROCEDURE :: fhash_tbl_get_int32_ptr, fhash_tbl_get_int64_ptr - PROCEDURE :: fhash_tbl_get_float_ptr, fhash_tbl_get_double_ptr - PROCEDURE :: fhash_tbl_get_char_ptr, fhash_tbl_get_logical_ptr - PROCEDURE :: fhash_tbl_get_raw_ptr - - GENERIC :: get_ptr => fhash_tbl_get_int32_ptr, fhash_tbl_get_int64_ptr - GENERIC :: get_ptr => fhash_tbl_get_float_ptr, fhash_tbl_get_double_ptr - GENERIC :: get_ptr => fhash_tbl_get_char_ptr, fhash_tbl_get_logical_ptr - GENERIC :: get_raw_ptr => fhash_tbl_get_raw_ptr - - FINAL :: fhash_tbl_cleanup - -END TYPE fhash_tbl_t - -CONTAINS - -!> Allocate hash table -SUBROUTINE fhash_tbl_allocate(tbl, size) - - !> Table object to allocate - CLASS(fhash_tbl_t), INTENT(inout) :: tbl - - !> Number of buckets in hash table - !> If ommited, `tbl` is allocated with `FHASH_DEFAULT_ALLOCATION` - INTEGER, INTENT(in), OPTIONAL :: size - - IF (PRESENT(size)) THEN - ALLOCATE (tbl%buckets(size)) - ELSE - ALLOCATE (tbl%buckets(FHASH_DEFAULT_ALLOCATION)) - END IF - -END SUBROUTINE fhash_tbl_allocate - -!> Finalizer for fhash_tbl_t -SUBROUTINE fhash_tbl_cleanup(tbl) - - !> Table object to allocate - TYPE(fhash_tbl_t), INTENT(inout) :: tbl - - INTEGER :: i - - IF (.NOT. ALLOCATED(tbl%buckets)) RETURN - - DO i = 1, SIZE(tbl%buckets) - - CALL sll_clean(tbl%buckets(i)) - - END DO - -END SUBROUTINE fhash_tbl_cleanup - -!> Unset a value in the table -!> -SUBROUTINE fhash_tbl_unset(tbl, key, stat) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(inout) :: tbl - - !> Key to remove - CLASS(fhash_key_t), INTENT(in) :: key - - !> Status flag. Zero if successful. - !> Unsuccessful: FHASH_EMPTY_TABLE | `FHASH_KEY_NOT_FOUND` - INTEGER, INTENT(out), OPTIONAL :: stat - - INTEGER :: index - LOGICAL :: found - - IF (PRESENT(stat)) stat = 0 - - IF (.NOT. ALLOCATED(tbl%buckets)) THEN - IF (PRESENT(stat)) stat = FHASH_EMPTY_TABLE - RETURN - END IF - - index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 - CALL sll_remove(tbl%buckets(index), key, found) - - IF (PRESENT(stat)) stat = MERGE(0, FHASH_KEY_NOT_FOUND, found) - -END SUBROUTINE fhash_tbl_unset - -!> Check if key exists in table -SUBROUTINE fhash_tbl_check_key(tbl, key, stat) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(in) :: tbl - - !> Key to retrieve - CLASS(fhash_key_t), INTENT(in) :: key - - !> Status flag. Zero if key is found. - !> Unsuccessful: `FHASH_EMPTY_TABLE` | `FHASH_KEY_NOT_FOUND` - INTEGER, INTENT(out) :: stat - - INTEGER :: index - LOGICAL :: found - TYPE(fhash_container_t), POINTER :: DATA - - IF (.NOT. ALLOCATED(tbl%buckets)) THEN - stat = FHASH_EMPTY_TABLE - RETURN - END IF - - stat = 0 - - index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 - - CALL sll_find_in(tbl%buckets(index), key, DATA, found) - - stat = MERGE(0, FHASH_KEY_NOT_FOUND, found) - - RETURN - -END SUBROUTINE fhash_tbl_check_key - -!> Get stats about the hash table -subroutine fhash_tbl_stats(tbl,num_buckets,num_items,num_collisions,max_depth) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(in) :: tbl - - !> Number of buckets allocated in table - INTEGER, INTENT(out), OPTIONAL :: num_buckets - - !> Number of key-value pairs stored in table - INTEGER, INTENT(out), OPTIONAL :: num_items - - !> Number of hash collisions - INTEGER, INTENT(out), OPTIONAL :: num_collisions - - !> Maximum depth of bucket in table - INTEGER, INTENT(out), OPTIONAL :: max_depth - - INTEGER :: i, depth - - ! Initialise stats - IF (PRESENT(num_items)) num_items = 0 - IF (PRESENT(num_collisions)) num_collisions = 0 - IF (PRESENT(max_depth)) max_depth = 0 - IF (PRESENT(num_buckets)) num_buckets = 0 - - IF (.NOT. ALLOCATED(tbl%buckets)) RETURN - - IF (PRESENT(num_buckets)) THEN - num_buckets = SIZE(tbl%buckets) - END IF - - DO i = 1, SIZE(tbl%buckets) - - depth = node_depth(tbl%buckets(i)) - - IF (PRESENT(num_items)) num_items = num_items + depth - - IF (PRESENT(num_collisions)) num_collisions = num_collisions + & - MERGE(depth - 1, 0, depth > 1) - - IF (PRESENT(max_depth)) max_depth = MAX(max_depth, depth) - - END DO - -END SUBROUTINE fhash_tbl_stats - -!> Set/update a polymorphic scalar value in the table -!> -!> `tbl` is allocated with default size if not already allocated -SUBROUTINE fhash_tbl_set_scalar(tbl, key, VALUE, POINTER) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(inout) :: tbl - - !> Key to set/update - CLASS(fhash_key_t), INTENT(in) :: key - - !> Value for key - CLASS(*), INTENT(in), TARGET :: VALUE - - !> If .true., store a pointer to value instead of copying - LOGICAL, INTENT(in), OPTIONAL :: POINTER - - INTEGER :: index - - IF (.NOT. ALLOCATED(tbl%buckets)) CALL fhash_tbl_allocate(tbl) - - index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 - - CALL sll_push_node(tbl%buckets(index), key, VALUE, POINTER) - -END SUBROUTINE fhash_tbl_set_scalar - -!> Get wrapper routine for generic 'set_ptr' -!> -!> `tbl` is allocated with default size if not already allocated -SUBROUTINE fhash_tbl_set_scalar_ptr(tbl, key, VALUE) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(inout) :: tbl - - !> Key to set/update - CLASS(fhash_key_t), INTENT(in) :: key - - !> Value for key - CLASS(*), INTENT(in), TARGET :: VALUE - - CALL fhash_tbl_set_scalar(tbl, key, VALUE, POINTER=.TRUE.) - -END SUBROUTINE fhash_tbl_set_scalar_ptr - -!> Retrieve data container from the hash table -SUBROUTINE fhash_tbl_get_data(tbl, key, DATA, stat) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(in) :: tbl - - !> Key to retrieve - CLASS(fhash_key_t), INTENT(in) :: key - - !> Copy of value retrieved for key - TYPE(fhash_container_t), POINTER :: DATA - - !> Status flag. Zero if successful. - !> Unsuccessful: `FHASH_EMPTY_TABLE` | `FHASH_KEY_NOT_FOUND` - INTEGER, INTENT(out), OPTIONAL :: stat - - INTEGER :: index - LOGICAL :: found - - IF (.NOT. ALLOCATED(tbl%buckets)) THEN - IF (PRESENT(stat)) stat = FHASH_EMPTY_TABLE - RETURN - END IF - - IF (PRESENT(stat)) stat = 0 - - index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 - - CALL sll_find_in(tbl%buckets(index), key, DATA, found) - - IF (.NOT. found) THEN - - IF (PRESENT(stat)) stat = FHASH_KEY_NOT_FOUND - RETURN - - END IF - -END SUBROUTINE fhash_tbl_get_data - -!> Get wrapper to retrieve a scalar intrinsic type value -subroutine fhash_tbl_get_intrinsic_scalar(tbl,key,i32,i64,r32,r64,char,raw,bool,stat) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(in) :: tbl - - !> Key to retrieve - CLASS(fhash_key_t), INTENT(in) :: key - - !> Value to retrieve - INTEGER(INT32), INTENT(out), OPTIONAL :: i32 - INTEGER(INT64), INTENT(out), OPTIONAL :: i64 - REAL(sp), INTENT(out), OPTIONAL :: r32 - REAL(dp), INTENT(out), OPTIONAL :: r64 - CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: char - LOGICAL, INTENT(out), OPTIONAL :: bool - CLASS(*), ALLOCATABLE, INTENT(out), OPTIONAL :: raw - - !> Status flag. Zero if successful. - !> Unsuccessful: `FHASH_EMPTY_TABLE` | - !> `FHASH_FOUND_WRONG_TYPE` | `FHASH_KEY_NOT_FOUND` - INTEGER, INTENT(out), OPTIONAL :: stat - - LOGICAL :: type_match - INTEGER :: local_stat - TYPE(fhash_container_t), POINTER :: DATA - - CHARACTER(:), ALLOCATABLE :: char_temp - - IF (PRESENT(stat)) stat = 0 - - CALL fhash_tbl_get_data(tbl, key, DATA, local_stat) - - IF (local_stat /= 0) THEN - IF (PRESENT(stat)) stat = local_stat - RETURN - END IF - - IF (PRESENT(char)) THEN ! (Work-around for weird gfortran bug re char dummy) - - CALL DATA%get(i32, i64, r32, r64, char_temp, bool, raw, type_match) - - IF (type_match) char = char_temp - - ELSE - - CALL DATA%get(i32, i64, r32, r64, bool=bool, raw=raw, match=type_match) - - END IF - - IF (.NOT. type_match) THEN - IF (PRESENT(stat)) stat = FHASH_FOUND_WRONG_TYPE - RETURN - END IF - -END SUBROUTINE fhash_tbl_get_intrinsic_scalar - -!> Get wrapper to retrieve a scalar intrinsic type pointer -subroutine fhash_tbl_get_intrinsic_scalar_ptr(tbl,key,i32,i64,r32,r64,char,bool,raw,stat) - - !> Hash table object - CLASS(fhash_tbl_t), INTENT(in) :: tbl - - !> Key to retrieve - CLASS(fhash_key_t), INTENT(in) :: key - - !> Value to retrieve - INTEGER(INT32), POINTER, INTENT(out), OPTIONAL :: i32 - INTEGER(INT64), POINTER, INTENT(out), OPTIONAL :: i64 - REAL(sp), POINTER, INTENT(out), OPTIONAL :: r32 - REAL(dp), POINTER, INTENT(out), OPTIONAL :: r64 - CHARACTER(:), POINTER, INTENT(out), OPTIONAL :: char - LOGICAL, POINTER, INTENT(out), OPTIONAL :: bool - CLASS(*), POINTER, INTENT(out), OPTIONAL :: raw - - !> Status flag. Zero if successful. - !> Unsuccessful: `FHASH_EMPTY_TABLE` | - !> `FHASH_FOUND_WRONG_TYPE` | `FHASH_KEY_NOT_FOUND` - INTEGER, INTENT(out), OPTIONAL :: stat - - LOGICAL :: type_match - INTEGER :: local_stat - TYPE(fhash_container_t), POINTER :: DATA - - CHARACTER(:), POINTER :: char_temp - - IF (PRESENT(stat)) stat = 0 - - CALL fhash_tbl_get_data(tbl, key, DATA, local_stat) - - IF (local_stat /= 0) THEN - IF (PRESENT(stat)) stat = local_stat - RETURN - END IF - - IF (PRESENT(char)) THEN ! (Work-around for weird gfortran bug re char dummy) - - CALL DATA%get_ptr(i32, i64, r32, r64, char_temp, bool, raw, type_match) - - IF (type_match) char => char_temp - - ELSE - - CALL DATA%get_ptr(i32, i64, r32, r64, bool=bool, raw=raw, match=type_match) - - END IF - - IF (.NOT. type_match) THEN - IF (PRESENT(stat)) stat = FHASH_FOUND_WRONG_TYPE - RETURN - END IF - -END SUBROUTINE fhash_tbl_get_intrinsic_scalar_ptr - -!> Get wrapper to directly retrieve a scalar int32 value -SUBROUTINE fhash_tbl_get_int32(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - INTEGER(INT32), INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, i32=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_int32 - -!> Get wrapper to directly retrieve a scalar int64 value -SUBROUTINE fhash_tbl_get_int64(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - INTEGER(INT64), INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, i64=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_int64 - -!> Get wrapper to directly retrieve a scalar float value -SUBROUTINE fhash_tbl_get_float(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - REAL(sp), INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, r32=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_float - -!> Get wrapper to directly retrieve a scalar double value -SUBROUTINE fhash_tbl_get_double(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - REAL(dp), INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, r64=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_double - -!> Get wrapper to directly retrieve a scalar character value -SUBROUTINE fhash_tbl_get_char(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - CHARACTER(:), ALLOCATABLE, INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, char=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_char - -!> Get wrapper to directly retrieve a scalar logical value -SUBROUTINE fhash_tbl_get_logical(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - LOGICAL, INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, bool=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_logical - -!> Get wrapper to directly retrieve underlying polymorhpic scalar value -SUBROUTINE fhash_tbl_get_raw(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - CLASS(*), ALLOCATABLE, INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar(tbl, key, raw=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_raw - -!> Get wrapper to directly retrieve a scalar int32 value -SUBROUTINE fhash_tbl_get_int32_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - INTEGER(INT32), POINTER, INTENT(out) :: VALUE !! Output value pointer - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, i32=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_int32_ptr - -!> Get wrapper to directly retrieve a scalar int64 value -SUBROUTINE fhash_tbl_get_int64_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - INTEGER(INT64), POINTER, INTENT(out) :: VALUE !! Output value pointer - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, i64=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_int64_ptr - -!> Get wrapper to directly retrieve a scalar float value -SUBROUTINE fhash_tbl_get_float_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - REAL(sp), POINTER, INTENT(out) :: VALUE !! Output value pointer - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, r32=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_float_ptr - -!> Get wrapper to directly retrieve a scalar double value -SUBROUTINE fhash_tbl_get_double_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - REAL(dp), POINTER, INTENT(out) :: VALUE !! Output value pointer - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, r64=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_double_ptr - -!> Get wrapper to directly retrieve a scalar character value -SUBROUTINE fhash_tbl_get_char_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - CHARACTER(:), POINTER, INTENT(out) :: VALUE !! Output value pointer - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, char=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_char_ptr - -!> Get wrapper to directly retrieve a scalar logical value -SUBROUTINE fhash_tbl_get_logical_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - LOGICAL, POINTER, INTENT(out) :: VALUE !! Output value pointer - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, bool=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_logical_ptr - -!> Get wrapper to directly retrieve underlying polymorhpic scalar value -SUBROUTINE fhash_tbl_get_raw_ptr(tbl, key, VALUE, stat) - CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object - CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve - CLASS(*), POINTER, INTENT(out) :: VALUE !! Output value - INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. - - CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, raw=VALUE, stat=stat) - -END SUBROUTINE fhash_tbl_get_raw_ptr - -END MODULE fhash_tbl diff --git a/src/modules/Fhash/src/fhash_tbl_iter.F90 b/src/modules/Fhash/src/fhash_tbl_iter.F90 deleted file mode 100644 index 45188529d..000000000 --- a/src/modules/Fhash/src/fhash_tbl_iter.F90 +++ /dev/null @@ -1,83 +0,0 @@ -MODULE fhash_tbl_iter -USE fhash_tbl, ONLY: fhash_tbl_t -USE fhash_key_base, ONLY: fhash_key_t -USE fhash_data_container, ONLY: fhash_container_t -USE fhash_sll -IMPLICIT NONE - -PRIVATE -PUBLIC fhash_iter_t - -!> Iterator type for iterating over hash table items -TYPE fhash_iter_t - - TYPE(fhash_tbl_t), POINTER :: tbl => NULL() - - INTEGER :: bucket = 1 - INTEGER :: depth = 1 - -CONTAINS - PROCEDURE :: next => fhash_iter_next - PROCEDURE :: reset => fhash_iter_reset -END TYPE fhash_iter_t - -INTERFACE fhash_iter_t - MODULE PROCEDURE :: fhash_iter_init -END INTERFACE fhash_iter_t - -CONTAINS - -!> Initialise fhash iterator -FUNCTION fhash_iter_init(tbl) RESULT(iter) - TYPE(fhash_tbl_t), INTENT(in), TARGET :: tbl - TYPE(fhash_iter_t) :: iter - - iter%tbl => tbl - -END FUNCTION fhash_iter_init - -!> Return next item from iterator -FUNCTION fhash_iter_next(iter, key, DATA) RESULT(found) - CLASS(fhash_iter_t), INTENT(inout) :: iter - CLASS(fhash_key_t), INTENT(out), ALLOCATABLE :: key - CLASS(*), ALLOCATABLE, INTENT(out) :: DATA - LOGICAL :: found - - TYPE(fhash_container_t), POINTER :: data_container - CLASS(*), POINTER :: data_out - - found = .FALSE. - - IF (.NOT. ASSOCIATED(iter%tbl)) RETURN - - DO WHILE (.NOT. found) - IF (iter%bucket > SIZE(iter%tbl%buckets)) RETURN - IF (.NOT. ALLOCATED(iter%tbl%buckets(iter%bucket)%key)) THEN - iter%bucket = iter%bucket + 1 - CYCLE - END IF - call sll_get_at(iter%tbl%buckets(iter%bucket),iter%depth,key,data_container,found) - IF (iter%depth > node_depth(iter%tbl%buckets(iter%bucket))) THEN - iter%bucket = iter%bucket + 1 - iter%depth = 1 - ELSE - iter%depth = iter%depth + 1 - END IF - END DO - - IF (found) THEN - CALL data_container%get(raw=DATA) ! Extract underlying polymorphic data - END IF - -END FUNCTION fhash_iter_next - -!> Reset iterator to beginning -SUBROUTINE fhash_iter_reset(iter) - CLASS(fhash_iter_t), INTENT(inout) :: iter - - iter%bucket = 1 - iter%depth = 1 - -END SUBROUTINE fhash_iter_reset - -END MODULE fhash_tbl_iter diff --git a/src/modules/FiniteElement/src/FiniteElement_Class.F90 b/src/modules/FiniteElement/src/FiniteElement_Class.F90 index d453184d3..84ace8b9d 100644 --- a/src/modules/FiniteElement/src/FiniteElement_Class.F90 +++ b/src/modules/FiniteElement/src/FiniteElement_Class.F90 @@ -46,8 +46,6 @@ MODULE FiniteElement_Class PROCEDURE, PUBLIC, PASS(obj) :: Initiate => fe_Initiate !! Constructor method for AbstractFE element !! This method can be overloaded by Subclass of this abstract class. - PROCEDURE, PUBLIC, PASS( obj ) :: InitiateLagrangeFE => & - & fe_InitiateLagrangeFE PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & fe_CheckEssentialParam END TYPE FiniteElement_ @@ -90,50 +88,6 @@ MODULE SUBROUTINE fe_Initiate(obj, param) END SUBROUTINE fe_Initiate END INTERFACE -!---------------------------------------------------------------------------- -! Initiate@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 27 Aug 2022 -! summary: Initiates an instance of the finite element - -INTERFACE - MODULE SUBROUTINE fe_InitiateLagrangeFE(obj, nsd, & - & elemType, baseContinuity, baseInterpolation, ipType, & - & basisType, alpha, beta, lambda, order) - CLASS(FiniteElement_), INTENT(INOUT) :: obj - INTEGER(I4B), INTENT(IN) :: nsd - !! Number of spatial dimension - INTEGER(I4B), INTENT(IN) :: elemType - !! Type of finite element - !! Line, Triangle, Quadrangle, Tetrahedron, Prism, Pyramid, - !! Hexahedron - CHARACTER(*), INTENT(IN) :: baseContinuity - !! Continuity or Conformity of basis function. - !! H1* (default), HDiv, HCurl, DG - CHARACTER(*), INTENT(IN) :: baseInterpolation - !! Basis function family used for interpolation. - !! LagrangeInterpolation, LagrangePolynomial - INTEGER(I4B), INTENT(IN) :: ipType - !! Interpolation point type, It is required when - !! baseInterpol is LagrangePolynomial. It can take following - !! values: - !! Legendre, Chebyshev, Ultraspherical, Equidistance, Jacobi - INTEGER(I4B), INTENT(IN) :: basisType - !! Basis type: - !! Legendre, Lobatto, Ultraspherical, Jacobi, Monomial - REAL(DFP), INTENT(IN) :: alpha - !! Jacobi parameter - REAL(DFP), INTENT(IN) :: beta - !! Jacobi parameter - REAL(DFP), INTENT(IN) :: lambda - !! Ultraspherical parameters - INTEGER(I4B), INTENT(IN) :: order - !! Isotropic Order of finite element - END SUBROUTINE fe_InitiateLagrangeFE -END INTERFACE - !---------------------------------------------------------------------------- ! Deallocate@Methods !---------------------------------------------------------------------------- @@ -196,6 +150,9 @@ MODULE SUBROUTINE SetFiniteElementParam( & !! Hexahedron CHARACTER(*), INTENT(IN) :: baseContinuity !! Continuity or Conformity of basis function. + !! This parameter is used to determine the nodal coordinates of + !! reference element, when xij is not present. + !! If xij is present then this parameter is ignored !! H1* (default), HDiv, HCurl, DG CHARACTER(*), INTENT(IN) :: baseInterpolation !! Basis function family used for interpolation. @@ -210,13 +167,9 @@ MODULE SUBROUTINE SetFiniteElementParam( & INTEGER(I4B), OPTIONAL, INTENT(IN) :: ipType !! Interpolation point type, It is required when !! baseInterpol is LagrangePolynomial - !! Legendre, Chebyshev, Ultraspherical, Equidistance - !! Jacobi INTEGER(I4B), OPTIONAL, INTENT(IN) :: basisType(:) - !! Basis type: - !! Legendre, Lobatto, Ultraspherical, + !! Basis type: Legendre, Lobatto, Ultraspherical, !! Jacobi, Monomial - !! Basis in x, y, and z direction. REAL(DFP), OPTIONAL, INTENT(IN) :: alpha(:) !! Jacobi parameter REAL(DFP), OPTIONAL, INTENT(IN) :: beta(:) @@ -245,11 +198,10 @@ END SUBROUTINE SetFiniteElementParam ! summary: Initiate vector of FiniteElement pointers INTERFACE Initiate - MODULE SUBROUTINE fe_Initiate1(obj, param, dom, dim) + MODULE SUBROUTINE fe_Initiate1(obj, param, dom) TYPE(FiniteElementPointer_), ALLOCATABLE, INTENT(INOUT) :: obj(:) TYPE(ParameterList_), INTENT(IN) :: param CLASS(Domain_), INTENT(IN) :: dom - INTEGER(I4B), INTENT(IN) :: dim END SUBROUTINE fe_Initiate1 END INTERFACE Initiate diff --git a/src/modules/Toml/CMakeLists.txt b/src/modules/Toml/CMakeLists.txt deleted file mode 100644 index c3395ef97..000000000 --- a/src/modules/Toml/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# 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}/TomlUtility.F90 -) diff --git a/src/modules/Toml/src/TomlUtility.F90 b/src/modules/Toml/src/TomlUtility.F90 deleted file mode 100644 index 8fc0515d1..000000000 --- a/src/modules/Toml/src/TomlUtility.F90 +++ /dev/null @@ -1,302 +0,0 @@ -! 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 TomlUtility -USE GlobalData -USE tomlf, ONLY: toml_table -USE TxtFile_Class -USE ExceptionHandler_Class, ONLY: e -IMPLICIT NONE -PRIVATE -CHARACTER(*), PARAMETER :: modName = "TomlUtility" -PUBLIC :: GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: GetValue Integer Vectors - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int8_r1(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT8), ALLOCATABLE, INTENT(OUT) :: VALUE(:) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int8_r1 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: GetValue Integer Vectors - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int16_r1(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT16), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int16_r1 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: GetValue Integer Vectors - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int32_r1(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT32), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int32_r1 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: GetValue Integer Vectors - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int64_r1(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT64), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int64_r1 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: GetValue Integer Vectors - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_real32_r1(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - REAL(REAL32), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_real32_r1 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: GetValue integer vectors - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_real64_r1(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - REAL(REAL64), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_real64_r1 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: Get values for a matrix - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int8_r2(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT8), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int8_r2 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: Get values for a matrix - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int16_r2(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT16), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int16_r2 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: Get values for a matrix - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int32_r2(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT32), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int32_r2 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: Get values for a matrix - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_int64_r2(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - INTEGER(INT64), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_int64_r2 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: Get values for a matrix - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_real32_r2(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - REAL(REAL32), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_real32_r2 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@Methods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-15 -! summary: Get values for a matrix - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_real64_r2(table, key, VALUE, origin, stat, & - & isFound) - TYPE(toml_table), INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: key - REAL(REAL64), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) - INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin - INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat - LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound - END SUBROUTINE toml_get_real64_r2 -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate table from toml file - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_from_file(table, afile) - TYPE(toml_table), ALLOCATABLE, INTENT(INOUT) :: table - TYPE(TxtFile_), INTENT(INOUT) :: afile - END SUBROUTINE toml_get_from_file -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! GetValue@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate table from toml file - -INTERFACE GetValue - MODULE SUBROUTINE toml_get_from_filename(table, filename) - TYPE(toml_table), ALLOCATABLE, INTENT(INOUT) :: table - CHARACTER(*), INTENT(IN) :: filename - END SUBROUTINE toml_get_from_filename -END INTERFACE GetValue - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -END MODULE TomlUtility diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 index 352179b99..4608ec207 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 @@ -17,10 +17,29 @@ SUBMODULE(AbstractBC_Class) ConstructorMethods USE BaseMethod -USE FPL_Method IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" +CALL e%raiseError(modName//'::'//myName//' - '// & + & 'This routine should be implemented by children of AbstractBC_') +END PROCEDURE bc_CheckEssentialParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_Initiate +CHARACTER(*), PARAMETER :: myName = "bc_Initiate" +CALL e%raiseError(modName//'::'//myName//' - '// & + & 'This routine should be implemented by children of AbstractBC_') +END PROCEDURE bc_Initiate + !---------------------------------------------------------------------------- ! Deallocate !---------------------------------------------------------------------------- @@ -46,153 +65,165 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_checkessentialparam -CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" +MODULE PROCEDURE AbstractBCcheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "AbstractBCcheckEssentialParam" INTEGER(I4B) :: ii -TYPE(String), ALLOCATABLE :: essentialParam(:) -TYPE(String) :: astr, prefix0 - -IF (PRESENT(prefix)) THEN - prefix0 = prefix -ELSE - prefix0 = obj%GetPrefix() -END IF +INTEGER(I4B), PARAMETER :: maxEssentialParam = 7 +TYPE(String) :: essentialParam(maxEssentialParam) + +essentialParam(1) = prefix//"/name" +essentialParam(2) = prefix//"/idof" +essentialParam(3) = prefix//"/nodalValueType" +essentialParam(4) = prefix//"/useFunction" +essentialParam(5) = prefix//"/isNormal" +essentialParam(6) = prefix//"/isTangent" +essentialParam(7) = prefix//"/useExternal" + +DO ii = 1, maxEssentialParam + IF (.NOT. param%isPresent(key=TRIM(essentialParam(ii)%chars()))) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & TRIM(essentialParam(ii)%chars())//' should be present in param') + END IF +END DO -astr = "/name/idof/nodalValueType/useFunction/isNormal/isTangent/useExternal" - -CALL astr%Split(essentialParam, sep="/") -CALL CheckEssentialParam(obj=param, & - & keys=essentialParam, & - & prefix=prefix0%chars(), & - & myName=myName, & - & modName=modName) -!NOTE: CheckEssentialParam param is defined in easifemClasses FPL_Method - -IF (ALLOCATED(essentialParam)) THEN - DO ii = 1, SIZE(essentialParam) - essentialParam(ii) = "" - END DO - DEALLOCATE (essentialParam) -END IF -astr = "" -prefix0 = "" -END PROCEDURE bc_CheckEssentialParam +END PROCEDURE AbstractBCcheckEssentialParam !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE SetAbstractBCParam -CHARACTER(*), PARAMETER :: myName = "SetAbstractBCParam()" +MODULE PROCEDURE setAbstractBCParam +INTEGER(I4B) :: ierr +CHARACTER(*), PARAMETER :: myName = "setAbstractBCParam" -CALL Set(param, datatype="char", prefix=prefix, key="name", & - & VALUE=input(option=name, default=default_name)) - -CALL Set(param, datatype=0_I4B, prefix=prefix, key="idof", & - & VALUE=input(option=idof, default=default_idof)) - -CALL Set(param, datatype=0_I4B, prefix=prefix, key="nodalValueType", & - & VALUE=input(option=nodalValueType, default=default_nodalValueType)) - -CALL Set(param, datatype=.TRUE., prefix=prefix, key="useFunction", & - & VALUE=input(option=useFunction, default=default_useFunction)) +IF (PRESENT(name)) THEN + ierr = param%set(key=TRIM(prefix)//"/name", VALUE=TRIM(name)) +ELSE + ierr = param%set(key=TRIM(prefix)//"/name", VALUE="AbstractBC") +END IF -CALL Set(param, datatype=.TRUE., prefix=prefix, key="isNormal", & - & VALUE=input(option=isNormal, default=default_isNormal)) +IF (PRESENT(idof)) THEN + ierr = param%set(key=TRIM(prefix)//"/idof", VALUE=idof) +ELSE + ierr = param%set(key=TRIM(prefix)//"/idof", VALUE=0_I4B) +END IF -CALL Set(param, datatype=.TRUE., prefix=prefix, key="isTangent", & - & VALUE=input(option=isTangent, default=default_isTangent)) +IF (PRESENT(nodalValueType)) THEN + ierr = param%set(key=TRIM(prefix)//"/nodalValueType", VALUE=nodalValueType) +ELSE + ierr = param%set(key=TRIM(prefix)//"/nodalValueType", VALUE=-1_I4B) +END IF -CALL Set(param, datatype=.TRUE., prefix=prefix, key="useExternal", & - & VALUE=input(option=useExternal, default=default_useExternal)) +IF (PRESENT(useFunction)) THEN + ierr = param%set(key=TRIM(prefix)//"/useFunction", VALUE=useFunction) +ELSE + ierr = param%set(key=TRIM(prefix)//"/useFunction", VALUE=.FALSE.) +END IF -IF (PRESENT(isNormal) .AND. PRESENT(idof)) THEN - IF (idof .GT. 0 .AND. isNormal) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: When isNormal is true, '// & - & 'idof CANNOT be greater than 0.') +IF (PRESENT(isNormal)) THEN + ierr = param%set(key=TRIM(prefix)//"/isNormal", VALUE=isNormal) + IF (PRESENT(idof)) THEN + IF (idof .GT. 0 .AND. isNormal) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'When isNormal is true, idof cannot be greater than 0') + END IF END IF +ELSE + ierr = param%set(key=TRIM(prefix)//"/isNormal", VALUE=.FALSE.) END IF -IF (PRESENT(isTangent) .AND. PRESENT(idof)) THEN - IF (idof .GT. 0 .AND. isTangent) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: When isTangent is true, '// & - & 'idof cannot be greater than 0.') +IF (PRESENT(isTangent)) THEN + ierr = param%set(key=TRIM(prefix)//"/isTangent", VALUE=isTangent) + IF (PRESENT(idof)) THEN + IF (idof .GT. 0 .AND. isTangent) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'When isTangent is true, idof cannot be greater than 0') + END IF END IF +ELSE + ierr = param%set(key=TRIM(prefix)//"/isTangent", VALUE=.FALSE.) END IF -END PROCEDURE SetAbstractBCParam +IF (PRESENT(useExternal)) THEN + ierr = param%set(key=TRIM(prefix)//"/useExternal", VALUE=useExternal) +ELSE + ierr = param%set(key=TRIM(prefix)//"/useExternal", VALUE=.FALSE.) +END IF + +END PROCEDURE setAbstractBCParam !---------------------------------------------------------------------------- -! Initiate +! AbstractBCInitiate !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_Initiate -CHARACTER(*), PARAMETER :: myName = "bc_Initiate()" -LOGICAL(LGT) :: isSelectionByMeshID, abool -TYPE(String) :: prefix +MODULE PROCEDURE AbstractBCInitiate +CHARACTER(*), PARAMETER :: myName = "AbstractBCInitiate" +CHARACTER(:), ALLOCATABLE :: char_var +INTEGER(I4B) :: ierr -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] Initiate()') -#endif - -prefix = obj%GetPrefix() -CALL obj%DEALLOCATE() +IF (obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'AbstractBC_ object is already initiated') +END IF -CALL obj%CheckEssentialParam(param=param, prefix=prefix%chars()) +CALL obj%checkEssentialParam(param=param) obj%isInitiated = .TRUE. obj%boundary = boundary obj%dom => dom - +! ! name -CALL GetValue(obj=param, prefix=prefix%chars(), key="name", VALUE=obj%name) - +! +ALLOCATE (CHARACTER(param%DataSizeInBytes( & + & key=TRIM(prefix)//"/name")) :: char_var) +ierr = param%get(key=TRIM(prefix)//"/name", VALUE=char_var) +obj%name = char_var +DEALLOCATE (char_var) +! ! idof -CALL GetValue(obj=param, prefix=prefix%chars(), key="idof", VALUE=obj%idof) - +! +ierr = param%get(key=TRIM(prefix)//"/idof", VALUE=obj%idof) +! ! nodalValueType -CALL GetValue(obj=param, prefix=prefix%chars(), key="nodalValueType", & +! +ierr = param%get(key=TRIM(prefix)//"/nodalValueType", & & VALUE=obj%nodalValueType) - +! ! useFunction -CALL GetValue(obj=param, prefix=prefix%chars(), key="useFunction", & +! +ierr = param%get(key=TRIM(prefix)//"/useFunction", & & VALUE=obj%useFunction) - +! ! isNormal -CALL GetValue(obj=param, prefix=prefix%chars(), key="isNormal", & +! +ierr = param%get(key=TRIM(prefix)//"/isNormal", & & VALUE=obj%isNormal) - +! ! isTangent -CALL GetValue(obj=param, prefix=prefix%chars(), key="isTangent", & +! +ierr = param%get(key=TRIM(prefix)//"/isTangent", & & VALUE=obj%isTangent) - +! ! useExternal -CALL GetValue(obj=param, prefix=prefix%chars(), key="useExternal", & +! +ierr = param%get(key=TRIM(prefix)//"/useExternal", & & VALUE=obj%useExternal) - +! ! check -CALL boundary%GetParam(isSelectionByMeshID=isSelectionByMeshID) -abool = boundary%isSelectionByMeshID & - & .AND. (.NOT. obj%useFunction) & - & .AND. (.NOT. obj%useExternal) & - & .AND. (obj%nodalValueType .NE. Constant) - -IF (abool) THEN - CALL e%RaiseWarning(modName//'::'//myName//" - "// & - & "When meshSelection is by MeshID"//CHAR_LF// & - & " and `useFunction` is false, then"//CHAR_LF// & - & " `nodalValueType` in `AbstractBC_`"//CHAR_LF// & - & " object should be Constant.") +! +IF (boundary%isSelectionByMeshID & + & .AND. (.NOT. obj%useFunction) & + & .AND. (.NOT. obj%useExternal)) THEN + IF (obj%nodalValueType .NE. Constant) THEN + CALL e%raiseWarning(modName//'::'//myName//" - "// & + & "When meshSelection is by MeshID & + & and `useFunction` is false, then & + & `nodalValueType` in `AbstractBC_` & + & object should be Constant.") + END IF END IF -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] AbstractBCInitiate()') -#endif -END PROCEDURE bc_Initiate +END PROCEDURE AbstractBCInitiate !---------------------------------------------------------------------------- ! diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 index 2ae68fc55..017a1f00a 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 @@ -142,24 +142,6 @@ END PROCEDURE bc_Get -!---------------------------------------------------------------------------- -! bc_GetFEVar -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_GetFEVar -CHARACTER(*), PARAMETER :: myName = "bc_GetFEVar()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine is under development.') - -! If useFunction is true then -! if constant -! if time -! if space -! if space-time - -! If useFunction is not true then -END PROCEDURE bc_GetFEVar - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -283,16 +265,7 @@ IF (PRESENT(nodalValueType)) nodalValueType = obj%nodalValueType IF (PRESENT(isInitiated)) isInitiated = obj%isInitiated IF (PRESENT(useExternal)) useExternal = obj%useExternal -END PROCEDURE bc_GetQuery -!---------------------------------------------------------------------------- -! GetPrefix -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_GetPrefix -CHARACTER(*), PARAMETER :: myName = "bc_GetPrefix()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child class.') -END PROCEDURE bc_GetPrefix +END PROCEDURE bc_GetQuery END SUBMODULE GetMethods diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 index 12f6c0d24..cf381f35f 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 @@ -17,49 +17,43 @@ SUBMODULE(AbstractBC_Class) IOMethods USE BaseMethod -USE TomlUtility -USE tomlf, ONLY: & - & toml_serialize, & - & toml_get => get_value, & - & toml_len => len, & - & toml_array, & - & toml_stat IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! Import +! !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Import CHARACTER(*), PARAMETER :: myName = "bc_Import" TYPE(String) :: dsetname, strval +INTEGER(I4B) :: ierr REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) IF (obj%isInitiated) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The object is already initiated, deallocate first!') END IF obj%isInitiated = .TRUE. obj%dom => dom -CALL e%RaiseInformation(modName//"::"//myName//" - "// & +CALL e%raiseInformation(modName//"::"//myName//" - "// & & "Importing Boundary condition") IF (.NOT. hdf5%isOpen()) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF IF (.NOT. hdf5%isRead()) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have read permission') END IF dsetname = TRIM(group)//"/name" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset name should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -68,7 +62,7 @@ dsetname = TRIM(group)//"/idof" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset idof should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -77,7 +71,7 @@ dsetname = TRIM(group)//"/nodalValueType" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset nodalValueType should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -96,7 +90,7 @@ dsetname = TRIM(group)//"/useFunction" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset useFunction should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -105,7 +99,7 @@ dsetname = TRIM(group)//"/useExternal" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset useExternal should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -114,7 +108,7 @@ dsetname = TRIM(group)//"/Boundary" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset Boundary, which is a group, should be present') ELSE CALL obj%boundary%IMPORT(hdf5=hdf5, group=dsetname%chars()) @@ -123,7 +117,7 @@ IF (.NOT. obj%UseFunction) THEN dsetname = TRIM(group)//"/NodalValue" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The dataset NodalValue should be present') END IF SELECT CASE (obj%nodalValueType) @@ -149,30 +143,31 @@ END PROCEDURE bc_Import !---------------------------------------------------------------------------- -! Export +! !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Export CHARACTER(*), PARAMETER :: myName = "bc_Export" TYPE(String) :: dsetname, strval +INTEGER(I4B) :: ierr REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) IF (.NOT. obj%isInitiated) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'The object is not initiated, initiate it first!') END IF -CALL e%RaiseInformation(modName//"::"//myName//" - "// & +CALL e%raiseInformation(modName//"::"//myName//" - "// & & "Exporting Dirichlet Boundary Condition") IF (.NOT. hdf5%isOpen()) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF IF (.NOT. hdf5%isWrite()) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have write permission') END IF @@ -219,7 +214,7 @@ IF (.NOT. obj%UseFunction) THEN dsetname = TRIM(group)//"/NodalValue" IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & + CALL e%raiseError(modName//'::'//myName//" - "// & & 'NodalValue is not allocated, it seems NodalValue is not set') END IF SELECT CASE (obj%nodalValueType) @@ -243,7 +238,7 @@ END PROCEDURE bc_Export !---------------------------------------------------------------------------- -! Display +! !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Display @@ -272,24 +267,24 @@ END SELECT CALL Display("# nodalValueType : "//TRIM(strval%chars()), unitNo=unitNo) -CALL Display(obj%useFunction, "useFunction : ", unitNo=unitNo) -CALL Display(obj%useExternal, "useExternal : ", unitNo=unitNo) +CALL Display(obj%useFunction, "# useFunction : ", unitNo=unitNo) +CALL Display(obj%useExternal, "# useExternal : ", unitNo=unitNo) CALL obj%Boundary%Display(msg="Boundary : ", unitNo=unitNo) IF (.NOT. obj%UseFunction) THEN IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL Display("NodalValue : NOT ALLOCATED", unitNo=unitNo) + CALL Display("# NodalValue : NOT ALLOCATED", unitNo=unitNo) ELSE SELECT CASE (obj%nodalValueType) CASE (Constant) real0 = obj%NodalValue(1, 1) - CALL Display(real0, "NodalValue : ", unitNo=unitNo) + CALL Display(real0, "# NodalValue : ", unitNo=unitNo) CASE (Space, Time) real1 = obj%NodalValue(:, 1) - CALL Display(real1, "NodalValue : ", unitNo=unitNo, orient="col") + CALL Display(real1, "# NodalValue : ", unitNo=unitNo, orient="col") CASE (SpaceTime) real2 = obj%NodalValue(:, :) - CALL Display(real2, "NodalValue : ", unitNo=unitNo) + CALL Display(real2, "# NodalValue : ", unitNo=unitNo) END SELECT END IF END IF @@ -298,229 +293,6 @@ IF (ALLOCATED(real2)) DEALLOCATE (real2) END PROCEDURE bc_Display -!---------------------------------------------------------------------------- -! ImportFromToml -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_ImportParamFromToml -CHARACTER(*), PARAMETER :: myName = "bc_ImportParamFromToml()" -INTEGER(I4B) :: origin, stat, nodalValueType, idof -LOGICAL(LGT) :: useFunction, isNormal, isTangent, useExternal -TYPE(String) :: nodalValueType_string, name, astr - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] ImportParamFromToml()') -#endif - -CALL toml_get(table, "useFunction", useFunction, & - & default_useFunction, origin=origin, stat=stat) - -CALL toml_get(table, "isTangent", isTangent, & - & default_isTangent, origin=origin, stat=stat) - -CALL toml_get(table, "isNormal", isNormal, & - & default_isNormal, origin=origin, stat=stat) - -CALL toml_get(table, "useExternal", useExternal, & - & default_useExternal, origin=origin, stat=stat) - -CALL toml_get(table, "nodalValueType", nodalValueType_string%raw, & - & default_nodalValueType_char, origin=origin, stat=stat) - -CALL toml_get(table, "idof", idof, default_idof, origin=origin, stat=stat) - -CALL toml_get(table, "name", name%raw, & - & obj%GetPrefix(), origin=origin, stat=stat) - -astr = nodalValueType_string%Upper() -SELECT CASE (astr%chars()) -CASE ("CONSTANT") - nodalValueType = Constant -CASE ("TIME") - nodalValueType = Time -CASE ("SPACE") - nodalValueType = Space -CASE ("SPACETIME") - nodalValueType = SpaceTime -CASE DEFAULT - nodalValueType = default_nodalValueType -END SELECT -astr = "" - -CALL SetAbstractBCParam( & - & param=param, & - & prefix=obj%GetPrefix(), & - & name=name%chars(), & - & idof=idof, & - & nodalValueType=nodalValueType, & - & useFunction=useFunction, & - & isNormal=isNormal, & - & isTangent=isTangent, & - & useExternal=useExternal & - & ) - -name = "" -nodalValueType_string = "" - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] ImportParamFromToml()') -#endif -END PROCEDURE bc_ImportParamFromToml - -!---------------------------------------------------------------------------- -! ImportFromToml -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_ImportFromToml1 -CHARACTER(*), PARAMETER :: myName = "meshSelect_ImportFromToml1()" -TYPE(ParameterList_) :: param -TYPE(toml_table), POINTER :: node -TYPE(MeshSelection_) :: boundary -INTEGER(I4B) :: origin, stat -LOGICAL(LGT) :: bool1, isFound -REAL(DFP), ALLOCATABLE :: value_r1(:), value_r2(:, :) -REAL(DFP) :: constantValue - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] ImportFromToml()') -#endif -CALL param%Initiate() - -CALL obj%ImportParamFromToml(param=param, table=table) - -node => NULL() -CALL toml_get(table, "boundary", node, origin=origin, requested=.FALSE., & - & stat=stat) - -IF (.NOT. ASSOCIATED(node)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: following error occured while reading '// & - & 'the toml file :: cannot find [boundary] table in config.') -END IF - -CALL boundary%ImportFromToml(table=node, dom=dom) -CALL obj%Initiate(param=param, boundary=boundary, dom=dom) - -IF (obj%useFunction) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: useFunction = .TRUE., currently you cannot '// & - & 'specify the function.') - RETURN -END IF - -SELECT CASE (obj%nodalValueType) -CASE (Constant) - CALL toml_get(table, "value", constantValue, origin=origin, stat=stat) - IF (stat .NE. toml_stat%success) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: nodalValueType is Constant. So, '// & - & 'value should be a constant (scalar real value).') - RETURN - END IF - CALL obj%Set(constantNodalValue=constantValue) - -CASE (Space, Time) - CALL GetValue(table=table, key="value", VALUE=value_r1, & - & isFound=isFound, origin=origin, stat=stat) - - bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) - - IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & - & 'value should be a vector of real numbers.'//CHAR_LF// & - & 'You can specify a vector by directly giving the vector values.'// & - & 'Otherwise, specify filename which contains the vector'// & - & 'values.') - RETURN - END IF - - IF (obj%nodalValueType .EQ. Space) THEN - CALL obj%Set(spaceNodalValue=value_r1) - ELSE - CALL obj%Set(timeNodalValue=value_r1) - END IF - -CASE (SpaceTime) - CALL GetValue(table=table, key="value", VALUE=value_r2, & - & isFound=isFound, origin=origin, stat=stat) - - bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) - - IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & - & 'value should be a vector of real numbers.'//CHAR_LF// & - & 'You can specify a vector by directly giving the vector values.'// & - & 'Otherwise, specify filename which contains the vector'// & - & 'values.') - RETURN - END IF - - CALL obj%Set(spaceTimeNodalValue=value_r2) - -END SELECT - -CALL param%DEALLOCATE() -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] ImportFromToml()') -#endif -END PROCEDURE bc_ImportFromToml1 - -!---------------------------------------------------------------------------- -! ImportFromToml -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_ImportFromToml2 -CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" -TYPE(toml_table), ALLOCATABLE :: table -TYPE(toml_table), POINTER :: node -INTEGER(I4B) :: origin, stat - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] ImportFromToml()') -#endif - -IF (PRESENT(afile)) THEN - CALL GetValue(table=table, afile=afile) -ELSEIF (PRESENT(filename)) THEN - CALL GetValue(table=table, filename=filename) -ELSE - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[ARG ERROR] :: either filename or afile should be present!') - RETURN -END IF - -node => NULL() -CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & - & stat=stat) - -IF (.NOT. ASSOCIATED(node)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: following error occured while reading '// & - & 'the toml file :: cannot find ['//tomlName//"] table in config.") -END IF - -CALL obj%ImportFromToml(table=node, dom=dom) - -#ifdef DEBUG_VER -IF (PRESENT(printToml)) THEN - CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & - & unitNo=stdout) -END IF -#endif - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] ImportParamFromToml()') -#endif -END PROCEDURE bc_ImportFromToml2 - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 index 1890a40b1..a1cbf4aa5 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 @@ -26,156 +26,172 @@ MODULE PROCEDURE bc_set CHARACTER(*), PARAMETER :: myName = "bc_set" -LOGICAL(LGT) :: notFunc_notExt, isTimeFunc, isSpaceFunc, isSTFunc, isFunc, & - & isConstVal, isSpaceVal, isSTVal, isTimeVal, bool1, bool2 IF (.NOT. obj%isInitiated) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & '[CONFIG ERROR ] :: AbstractBC_ object is not initiated.') + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'AbstractBC_ object is not initiated, initiate it first.') END IF -notFunc_notExt = (.NOT. obj%useFunction) .AND. & -& (.NOT. obj%useExternal) - -isTimeFunc = PRESENT(timeFunction) -isSpaceFunc = PRESENT(spaceFunction) -isSTFunc = PRESENT(spaceTimeFunction) -isFunc = isSpaceFunc .OR. isTimeFunc .OR. isSTFunc -isConstVal = PRESENT(constantNodalValue) -isSpaceVal = PRESENT(spaceNodalValue) -isTimeVal = PRESENT(timeNodalValue) -isSTVal = PRESENT(spaceTimeNodalValue) - -IF (notFunc_notExt .AND. isFunc) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "//CHAR_LF// & - & "with useFunction=.FALSE. and useExternal=.FALSE."//CHAR_LF// & - & "So you cannot provide timeFunction, spaceFunction, spaceTimeFunction") -END IF +IF (.NOT. obj%UseFunction .AND. .NOT. obj%useExternal) THEN -bool1 = notFunc_notExt .AND. isConstVal -bool2 = bool1 .AND. obj%nodalValueType .NE. Constant -IF (bool2) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & - & "with nodalValueType=Constant "//CHAR_LF// & - & 'So, constantNodalValue cannot be present') - RETURN -END IF + IF (PRESENT(TimeFunction) .OR. PRESENT(SpaceFunction) & + & .OR. PRESENT(SpaceTimeFunction)) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is initiated with useFunction=.FALSE."//CHAR_LF// & + & " and useExternal=.FALSE."//CHAR_LF// & + & "So you cannot provide TimeFunction, SpaceFunction, SpaceTimeFunction") + END IF -! constant -IF (bool1) THEN - CALL Reallocate(obj%NodalValue, 1, 1) - obj%NodalValue = constantNodalValue - RETURN -END IF + ! constant -! spaceNodalValue -bool1 = notFunc_notExt .AND. isSpaceVal -bool2 = bool1 .AND. (obj%nodalValueType .NE. Space) -IF (bool2) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & - & "with nodalValueType=Space"//CHAR_LF// & - & 'So, spaceNodalValue cannot be present.') - RETURN -END IF + IF (PRESENT(ConstantNodalValue)) THEN -IF (bool1) THEN - CALL Reallocate(obj%NodalValue, SIZE(spaceNodalValue), 1) - obj%NodalValue(:, 1) = spaceNodalValue - RETURN -END IF + IF (obj%nodalValueType .NE. Constant) THEN -! timeNodalValue -bool1 = notFunc_notExt .AND. isTimeVal -bool2 = bool1 .AND. (obj%nodalValueType .NE. Time) -IF (bool2) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & - & "with nodalValueType=Time"//CHAR_LF// & - & 'So, timeNodalValue cannot be present.') - RETURN -END IF + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=Constant"// & + & CHAR_LF// & + & 'So, ConstantNodalValue cannot be present') -IF (bool1) THEN - CALL Reallocate(obj%NodalValue, SIZE(timeNodalValue), 1) - obj%NodalValue(:, 1) = timeNodalValue - RETURN -END IF + ELSE -! spaceTimeNodalValue -bool1 = notFunc_notExt .AND. isSTVal -bool2 = bool1 .AND. (obj%nodalValueType .NE. SpaceTime) -IF (bool2) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & - & " nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, spaceTimeNodalValue cannot be present') - RETURN -END IF -IF (bool1) THEN - obj%NodalValue = spaceTimeNodalValue - RETURN -END IF + CALL Reallocate(obj%NodalValue, 1, 1) + obj%NodalValue = ConstantNodalValue + RETURN -! spaceFunction -bool1 = isSpaceFunc .AND. (obj%nodalValueType .NE. Space) -IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & - & "with nodalValueType=Space"// & - & CHAR_LF// & - & 'So, spaceFunction cannot be present') - RETURN -END IF + END IF -IF (isSpaceFunc) THEN - obj%spaceFunction => spaceFunction - RETURN -END IF + END IF -! timeFunction -bool1 = isTimeFunc .AND. (obj%nodalValueType .NE. Time) -IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & - & "nodalValueType=Time"// & - & CHAR_LF// & - & 'So, timeFunction cannot be present') - RETURN -END IF + ! SpaceNodalValue -IF (isTimeFunc) THEN - obj%timeFunction => timeFunction - RETURN -END IF + IF (PRESENT(SpaceNodalValue)) THEN -! spaceTimeFunction -bool1 = isSTFunc .AND. (obj%nodalValueType .NE. SpaceTime) -IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & - & "nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, spaceTimeFunction cannot be present') - RETURN -END IF + IF (obj%nodalValueType .NE. Space) THEN -IF (isSTFunc) THEN - obj%spaceTimeFunction => spaceTimeFunction - RETURN -END IF + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=Space"// & + & CHAR_LF// & + & 'So, SpaceNodalValue cannot be present') + + ELSE + + CALL Reallocate(obj%NodalValue, SIZE(SpaceNodalValue), 1) + obj%NodalValue(:, 1) = SpaceNodalValue + RETURN + + END IF + + END IF + + ! TimeNodalValue + + IF (PRESENT(TimeNodalValue)) THEN + + IF (obj%nodalValueType .NE. Time) THEN + + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=Time"// & + & CHAR_LF// & + & 'So, TimeNodalValue cannot be present') + + ELSE + + CALL Reallocate(obj%NodalValue, SIZE(TimeNodalValue), 1) + obj%NodalValue(:, 1) = TimeNodalValue + RETURN + + END IF + + END IF + + ! SpaceTimeNodalValue + + IF (PRESENT(SpaceTimeNodalValue)) THEN + + IF (obj%nodalValueType .NE. SpaceTime) THEN + + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=SpaceTime"// & + & CHAR_LF// & + & 'So, SpaceTimeNodalValue cannot be present') + + ELSE + + obj%NodalValue = SpaceTimeNodalValue + RETURN + + END IF + + END IF + +ELSE + + ! SpaceFunction + + IF (PRESENT(SpaceFunction)) THEN + + IF (obj%nodalValueType .NE. Space) THEN + + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=Space"// & + & CHAR_LF// & + & 'So, SpaceFunction cannot be present') + + ELSE + + obj%SpaceFunction => SpaceFunction + RETURN + + END IF + + END IF + + ! TimeNodalValue + + IF (PRESENT(TimeFunction)) THEN + + IF (obj%nodalValueType .NE. Time) THEN + + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=Time"// & + & CHAR_LF// & + & 'So, TimeFunction cannot be present') + + ELSE + + obj%TimeFunction => TimeFunction + RETURN + + END IF + + END IF + + ! SpaceTimeNodalValue + + IF (PRESENT(SpaceTimeFunction)) THEN + + IF (obj%nodalValueType .NE. SpaceTime) THEN + + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is not initiated with nodalValueType=SpaceTime"// & + & CHAR_LF// & + & 'So, SpaceTimeFunction cannot be present') + + ELSE + + obj%SpaceTimeFunction => SpaceTimeFunction + RETURN + + END IF + + END IF + + CALL e%raiseError(modName//'::'//myName//" - "// & + & "AbstractBC_::obj is initiated with useFunction=TRUE"// & + & CHAR_LF// & + & 'So, SpaceFunction, TimeFunction, or SpaceTimeFunction should be present') -IF (obj%useFunction .AND. (.NOT. isFunc)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "// & - & "with useFunction=TRUE"// & - & CHAR_LF// & - & 'So, spaceFunction, timeFunction, or spaceTimeFunction '// & - & 'should be present') - RETURN END IF END PROCEDURE bc_set diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 index 8ba7af4f3..b37d055f4 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 @@ -19,6 +19,45 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_checkEssentialParam +CALL AbstractBCcheckEssentialParam(& + & obj=obj, & + & param=param, & + & prefix=myprefix) +END PROCEDURE bc_checkEssentialParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetDirichletBCParam +CALL SetAbstractBCParam(& + & param=param, & + & prefix=myprefix, & + & name=name, & + & idof=idof, & + & nodalValueType=nodalValueType, & + & useFunction=input(option=useFunction, default=.FALSE.), & + & isNormal=input(option=isNormal, default=.FALSE.), & + & isTangent=input(option=isTangent, default=.FALSE.)) +END PROCEDURE SetDirichletBCParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_Initiate +CALL AbstractBCInitiate(obj=obj, & +& param=param, & +& prefix=myprefix, & +& boundary=boundary, & +& dom=dom) +END PROCEDURE bc_Initiate + !---------------------------------------------------------------------------- ! Final !---------------------------------------------------------------------------- @@ -65,11 +104,6 @@ MODULE PROCEDURE bc_AddDirichletBC CHARACTER(*), PARAMETER :: myName = "bc_AddDirichletBC" -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] AddDirichletBC()') -#endif - IF (dbcNo .GT. SIZE(dbc)) THEN CALL e%raiseError(modName//'::'//myName//" - "// & & '[OUT OF BOUND ERROR] :: dbcNo [= '//TOSTRING(dbcNo)// & @@ -90,10 +124,6 @@ & boundary=boundary, & & dom=dom) -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] AddDirichletBC()') -#endif END PROCEDURE bc_AddDirichletBC END SUBMODULE ConstructorMethods diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 index cbb5196f6..a5e2676b3 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 @@ -42,12 +42,4 @@ END PROCEDURE bc_GetDirichletBCPointer -!---------------------------------------------------------------------------- -! GetPrefix -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_GetPrefix - ans = myprefix -END PROCEDURE bc_GetPrefix - END SUBMODULE GetMethods diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 index 68c12fa03..19e6ac5e2 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 @@ -16,105 +16,6 @@ ! SUBMODULE(DirichletBC_Class) IOMethods -USE BaseMethod -USE TomlUtility -USE tomlf, ONLY: & - & toml_serialize, & - & toml_get => get_value, & - & toml_len => len, & - & toml_array, & - & toml_stat IMPLICIT NONE CONTAINS - -!---------------------------------------------------------------------------- -! ImportFromToml -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_ImportFromToml1 -CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml1()" -TYPE(toml_table), POINTER :: node -TYPE(toml_array), POINTER :: array -INTEGER(I4B) :: origin, stat, tsize, ii, tsize1 - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] ImportFromToml()') -#endif - -tsize1 = SIZE(obj) - -array => NULL() -CALL toml_get(table, tomlName, array, origin=origin, & - & requested=.FALSE., stat=stat) - -IF (.NOT. ASSOCIATED(array)) THEN - IF (tsize1 .GT. 0_I4B) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & 'In toml file :: cannot find ['//tomlName//"] table.") - ELSE - CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & 'In toml file :: cannot find ['//tomlName//"] table.") - END IF - RETURN -END IF - -tsize = toml_len(array) -IF (tsize .NE. tsize1) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: The number of boundary condition '// char_lf// & - & ' in the toml config ('//tostring(tsize)//') is not same '// & - & ' as the size of obj ('//tostring(tsize1)//")") - RETURN -END IF - -DO ii = 1, tsize - node => NULL() - CALL toml_get(array, ii, node) - IF (.NOT. ASSOCIATED(node)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: DirichletBC '//tostring(ii)// & - & ' cannot be read from the toml file.') - END IF - IF (.NOT. ASSOCIATED(obj(ii)%ptr)) ALLOCATE (obj(ii)%ptr) - CALL obj(ii)%ptr%ImportFromToml(table=node, dom=dom) -END DO - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] ImportParamFromToml()') -#endif -END PROCEDURE bc_ImportFromToml1 - -!---------------------------------------------------------------------------- -! ImportFromToml -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_ImportFromToml2 -CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" -TYPE(toml_table), ALLOCATABLE :: table - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] ImportFromToml()') -#endif - -IF (PRESENT(afile)) THEN - CALL GetValue(table=table, afile=afile) -ELSEIF (PRESENT(filename)) THEN - CALL GetValue(table=table, filename=filename) -ELSE - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[ARG ERROR] :: either filename or afile should be present!') - RETURN -END IF - -CALL DirichletBCImportFromToml(obj=obj, table=table, dom=dom, & - & tomlName=tomlName) - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] ImportParamFromToml()') -#endif -END PROCEDURE bc_ImportFromToml2 END SUBMODULE IOMethods diff --git a/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 b/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 index b91075abf..b5f9e9de3 100644 --- a/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 +++ b/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 @@ -20,7 +20,7 @@ CONTAINS !---------------------------------------------------------------------------- -! Initiate +! Initiate !---------------------------------------------------------------------------- MODULE PROCEDURE fe_Initiate @@ -28,7 +28,7 @@ END PROCEDURE fe_Initiate !---------------------------------------------------------------------------- -! CheckEssentialParam +! CheckEssentialParam !---------------------------------------------------------------------------- MODULE PROCEDURE fe_CheckEssentialParam @@ -41,22 +41,22 @@ MODULE PROCEDURE SetFiniteElementParam CALL SetAbstractFEParam( & - & param=param, & - & prefix=myprefix, & - & nsd=nsd, & - & elemType=elemType, & - & baseContinuity=baseContinuity, & - & baseInterpolation=baseInterpolation, & - & ipType=ipType, & - & basisType=basisType, & - & alpha=alpha, & - & beta=beta, & - & lambda=lambda, & - & order=order, & - & anisoOrder=anisoOrder, & - & edgeOrder=edgeOrder, & - & faceOrder=faceOrder, & - & cellOrder=cellOrder) +& param=param, & +& prefix=myprefix, & +& nsd=nsd, & +& elemType=elemType, & +& baseContinuity=baseContinuity, & +& baseInterpolation=baseInterpolation, & +& ipType=ipType, & +& basisType=basisType, & +& alpha=alpha, & +& beta=beta, & +& lambda=lambda, & +& order=order, & +& anisoOrder=anisoOrder, & +& edgeOrder=edgeOrder, & +& faceOrder=faceOrder, & +& cellOrder=cellOrder) END PROCEDURE SetFiniteElementParam !---------------------------------------------------------------------------- @@ -97,73 +97,32 @@ MODULE PROCEDURE fe_Initiate1 CHARACTER(*), PARAMETER :: myName = "fe_Initiate1()" TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr, ii, tsize -INTEGER(I4B), ALLOCATABLE :: elemType(:), order(:) +INTEGER(I4B) :: ierr, ii, tElemType +INTEGER(I4B), ALLOCATABLE :: elemType(:) sublist => NULL() -IF (.NOT. param%isSubList(key=myPrefix)) RETURN - -ierr = param%GetSubList(key=myprefix, sublist=sublist) - -IF (ierr .NE. 0) THEN +IF (.NOT. param%isSubList(key=myPrefix)) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured while getting'// & - & ' the sublist from param.') + & '[ARGUMENT ERROR] :: '//myprefix//' should be a sublist') END IF -elemType = dom%GetElemType(dim=dim) -order = dom%GetOrder(dim=dim) -tsize = SIZE(elemType) +ierr = param%GetSubList(key=myprefix, sublist=sublist) + +elemType = dom%GetElemType(dim=-1_I4B) +tElemType = SIZE(elemType) CALL DEALLOCATE (obj) -ALLOCATE (obj(tsize)) +ALLOCATE(obj(tElemType) ) -DO ii = 1, tsize +DO ii = 1, SIZE(elemType) ierr = sublist%Set(key=myprefix//"/elemType", VALUE=elemType(ii)) - ierr = sublist%Set(key=myprefix//"/order", VALUE=order(ii)) - ALLOCATE (FiniteElement_ :: obj(ii)%ptr) + ALLOCATE(FiniteElement_::obj(ii)%ptr) CALL obj(ii)%ptr%Initiate(param=param) END DO sublist => NULL() IF (ALLOCATED(elemType)) DEALLOCATE (elemType) -IF (ALLOCATED(order)) DEALLOCATE (order) END PROCEDURE fe_Initiate1 -!---------------------------------------------------------------------------- -! InitiateLagrangeFE -!---------------------------------------------------------------------------- - -MODULE PROCEDURE fe_InitiateLagrangeFE -TYPE(ParameterList_) :: param -CHARACTER(*), PARAMETER :: myName="fe_InitiateLagrangeFE()" - -IF (baseInterpolation .NE. "LagrangePolynomial" & - & .OR. baseInterpolation .NE. "LagrangeInterpolation") THEN - CALL e%RaiseError(modName //'::'//myName// ' - '// & - & '[ARG ERROR] :: This routine is valid for baseInterpolation = ' // & - & 'LagrangePolynomial or LagrangeInterpolation ' // & - & ' given value of baseInterpolation is ' // trim(baseInterpolation)) -END IF - -CALL param%Initiate() -CALL SetFiniteElementParam( & - & param=param, & - & nsd=nsd, & - & elemType=elemType, & - & baseContinuity=baseContinuity, & - & baseInterpolation=baseInterpolation, & - & ipType=ipType, & - & basisType=[basisType], & - & alpha=[alpha], & - & beta=[beta], & - & lambda=[lambda], & - & order=order) - -CALL obj%Initiate(param) - -CALL param%DEALLOCATE() -END PROCEDURE fe_InitiateLagrangeFE - END SUBMODULE Methods diff --git a/src/submodules/Toml/CMakeLists.txt b/src/submodules/Toml/CMakeLists.txt deleted file mode 100644 index 7917e32bf..000000000 --- a/src/submodules/Toml/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# 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}/TomlUtility@GetMethods.F90 -) diff --git a/src/submodules/Toml/src/TomlUtility@GetMethods.F90 b/src/submodules/Toml/src/TomlUtility@GetMethods.F90 deleted file mode 100644 index 6a6ebcd87..000000000 --- a/src/submodules/Toml/src/TomlUtility@GetMethods.F90 +++ /dev/null @@ -1,199 +0,0 @@ -! 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(TomlUtility) GetMethods -USE String_Class -USE TxtFile_Class -USE BaseMethod -USE tomlf, ONLY: & - & toml_error, & - & toml_load, & - & toml_parser_config, & - & toml_serialize, & - & toml_get => get_value, & - & toml_len => len, & - & toml_context, & - & toml_terminal, & - & toml_load, & - & toml_array, & - & toml_stat -IMPLICIT NONE -CONTAINS - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int8_r1 -#include "./include/ReadVector.inc" -END PROCEDURE toml_get_int8_r1 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int16_r1 -#include "./include/ReadVector.inc" -END PROCEDURE toml_get_int16_r1 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int32_r1 -#include "./include/ReadVector.inc" -END PROCEDURE toml_get_int32_r1 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int64_r1 -#include "./include/ReadVector.inc" -END PROCEDURE toml_get_int64_r1 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_real32_r1 -#include "./include/ReadVector.inc" -END PROCEDURE toml_get_real32_r1 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_real64_r1 -#include "./include/ReadVector.inc" -END PROCEDURE toml_get_real64_r1 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int8_r2 -#include "./include/ReadMatrix.inc" -END PROCEDURE toml_get_int8_r2 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int16_r2 -#include "./include/ReadMatrix.inc" -END PROCEDURE toml_get_int16_r2 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int32_r2 -#include "./include/ReadMatrix.inc" -END PROCEDURE toml_get_int32_r2 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_int64_r2 -#include "./include/ReadMatrix.inc" -END PROCEDURE toml_get_int64_r2 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_real32_r2 -#include "./include/ReadMatrix.inc" -END PROCEDURE toml_get_real32_r2 - -!---------------------------------------------------------------------------- -! Get -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_real64_r2 -#include "./include/ReadMatrix.inc" -END PROCEDURE toml_get_real64_r2 - -!---------------------------------------------------------------------------- -! toml_get_from_file -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_from_file -CHARACTER(*), PARAMETER :: myName = "toml_get_from_file()" -LOGICAL(LGT) :: isNotOpen, isNotRead -LOGICAL(LGT), PARAMETER :: color = .TRUE. -INTEGER(I4B), PARAMETER :: detail = 1 -TYPE(toml_error), ALLOCATABLE :: error -TYPE(toml_context) :: context -TYPE(toml_terminal) :: terminal - -terminal = toml_terminal(color) -isNotOpen = .NOT. afile%IsOpen() -isNotRead = .NOT. afile%IsRead() - -IF (isNotRead .OR. isNotOpen) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: The file is not open or does not have '// & - & 'the access to read!') -END IF - -CALL toml_load(table, & - & afile%GetUnitNo(), & - & context=context, & - & config=toml_parser_config(color=terminal, context_detail=detail), & - & error=error & - & ) - -IF (ALLOCATED(error)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & - & ' with following message: '//CHAR_LF//error%message) -END IF - -END PROCEDURE toml_get_from_file - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE toml_get_from_filename -CHARACTER(*), PARAMETER :: myName = "toml_get_from_filename()" -LOGICAL(LGT), PARAMETER :: color = .TRUE. -INTEGER(I4B), PARAMETER :: detail = 1 -TYPE(toml_error), ALLOCATABLE :: error -TYPE(toml_context) :: context -TYPE(toml_terminal) :: terminal - -terminal = toml_terminal(color) -CALL toml_load(table, & - & filename, & - & context=context, & - & config=toml_parser_config(color=terminal, context_detail=detail), & - & error=error & - & ) - -IF (ALLOCATED(error)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & - & ' with following message: '//CHAR_LF//error%message) -END IF - -END PROCEDURE toml_get_from_filename - -END SUBMODULE GetMethods From 4e18fad04daa6b8b0f66cca6a4c167e3cba62399 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 15:30:43 +0900 Subject: [PATCH 011/117] Updating easifemClasses --- cmake/Compiler.cmake | 29 +- cmake/Config.cmake.in | 2 - cmake/addGmsh-old.cmake | 35 ++ cmake/addGmsh.cmake | 30 +- cmake/targetCompileDefs.cmake | 4 +- cmake/targetLinkLibs.cmake | 43 -- install.py | 4 +- src/modules/AbstractBC/CMakeLists.txt | 19 +- src/modules/AbstractBC/src/AbstractBC.toml | 61 ++ .../AbstractBC/src/AbstractBC_Class.F90 | 288 ++++++--- .../AbstractFE/src/AbstractFE_Class.F90 | 3 +- .../DirichletBC/src/DirichletBC_Class.F90 | 109 ++-- src/modules/Fhash/CMakeLists.txt | 19 + src/modules/Fhash/src/fhash.F90 | 14 + .../Fhash/src/fhash_data_container.F90 | 241 ++++++++ src/modules/Fhash/src/fhash_fnv.F90 | 181 ++++++ src/modules/Fhash/src/fhash_key/base.F90 | 42 ++ src/modules/Fhash/src/fhash_key/char.F90 | 76 +++ src/modules/Fhash/src/fhash_key/int32.F90 | 76 +++ src/modules/Fhash/src/fhash_key/int32_1d.F90 | 82 +++ src/modules/Fhash/src/fhash_key/int64.F90 | 76 +++ src/modules/Fhash/src/fhash_key/int64_1d.F90 | 82 +++ src/modules/Fhash/src/fhash_sll.F90 | 277 +++++++++ src/modules/Fhash/src/fhash_tbl.F90 | 571 ++++++++++++++++++ src/modules/Fhash/src/fhash_tbl_iter.F90 | 83 +++ .../FiniteElement/src/FiniteElement_Class.F90 | 58 +- src/modules/Toml/CMakeLists.txt | 22 + src/modules/Toml/src/TomlUtility.F90 | 302 +++++++++ .../AbstractBC_Class@ConstructorMethods.F90 | 241 ++++---- .../src/AbstractBC_Class@GetMethods.F90 | 29 +- .../src/AbstractBC_Class@IOMethods.F90 | 282 ++++++++- .../src/AbstractBC_Class@SetMethods.F90 | 280 ++++----- .../DirichletBC_Class@ConstructorMethods.F90 | 48 +- .../src/DirichletBC_Class@GetMethods.F90 | 8 + .../src/DirichletBC_Class@IOMethods.F90 | 99 +++ .../src/FiniteElement_Class@Methods.F90 | 99 ++- src/submodules/Toml/CMakeLists.txt | 22 + .../Toml/src/TomlUtility@GetMethods.F90 | 199 ++++++ 38 files changed, 3548 insertions(+), 588 deletions(-) create mode 100644 cmake/addGmsh-old.cmake create mode 100644 src/modules/AbstractBC/src/AbstractBC.toml create mode 100644 src/modules/Fhash/CMakeLists.txt create mode 100644 src/modules/Fhash/src/fhash.F90 create mode 100644 src/modules/Fhash/src/fhash_data_container.F90 create mode 100644 src/modules/Fhash/src/fhash_fnv.F90 create mode 100644 src/modules/Fhash/src/fhash_key/base.F90 create mode 100644 src/modules/Fhash/src/fhash_key/char.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int32.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int32_1d.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int64.F90 create mode 100644 src/modules/Fhash/src/fhash_key/int64_1d.F90 create mode 100644 src/modules/Fhash/src/fhash_sll.F90 create mode 100644 src/modules/Fhash/src/fhash_tbl.F90 create mode 100644 src/modules/Fhash/src/fhash_tbl_iter.F90 create mode 100644 src/modules/Toml/CMakeLists.txt create mode 100644 src/modules/Toml/src/TomlUtility.F90 create mode 100644 src/submodules/Toml/CMakeLists.txt create mode 100644 src/submodules/Toml/src/TomlUtility@GetMethods.F90 diff --git a/cmake/Compiler.cmake b/cmake/Compiler.cmake index b3a46043b..067043f78 100644 --- a/cmake/Compiler.cmake +++ b/cmake/Compiler.cmake @@ -31,7 +31,34 @@ ENDIF() IF (${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU" OR Fortran_COMPILER_NAME MATCHES "gfortran*") LIST(APPEND FORTRAN_FLAGS "-ffree-form" "-ffree-line-length-none" "-std=f2018" "-fimplicit-none" ) LIST(APPEND FORTRAN_FLAGS_RELEASE "-O3" ) - LIST(APPEND FORTRAN_FLAGS_DEBUG "-fbounds-check" "-g" "-fbacktrace" "-Wextra" "-Wall" "-fprofile-arcs" "-ftest-coverage" "-Wimplicit-interface" ) + + IF(APPLE) + LIST( + APPEND + FORTRAN_FLAGS_DEBUG + "-fbounds-check" + "-g" + "-fbacktrace" + "-Wextra" + "-Wall" + # "-fprofile-arcs" + "-ftest-coverage" + "-Wimplicit-interface" + ) + ELSE() + LIST( + APPEND + FORTRAN_FLAGS_DEBUG + "-fbounds-check" + "-g" + "-fbacktrace" + "-Wextra" + "-Wall" + # "-fprofile-arcs" + "-ftest-coverage" + "-Wimplicit-interface" + ) + ENDIF() ELSEIF(${CMAKE_Fortran_COMPILER_ID} STREQUAL "Intel" OR Fortran_COMPILER_NAME MATCHES "ifort*") LIST(APPEND FORTRAN_FLAGS "-r8" "-W1") diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in index 53bcc9b97..a8049d31c 100644 --- a/cmake/Config.cmake.in +++ b/cmake/Config.cmake.in @@ -28,8 +28,6 @@ # find_package(easifemBase 1.0.0 CONFIG REQUIRED) # # The following variables can be set to guide the search for this package: -# -# @PACKAGE_INIT@ diff --git a/cmake/addGmsh-old.cmake b/cmake/addGmsh-old.cmake new file mode 100644 index 000000000..897195819 --- /dev/null +++ b/cmake/addGmsh-old.cmake @@ -0,0 +1,35 @@ +# 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 +# +#GMSH SDK +IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) + OPTION( USE_GMSH_SDK OFF ) + IF( USE_GMSH_SDK ) + LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) + IF( UNIX ) + IF(APPLE) + SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) + ELSE() + # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) + SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) + ENDIF() + ENDIF() + TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) + MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) + ELSE() + MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) + ENDIF() +ENDIF() diff --git a/cmake/addGmsh.cmake b/cmake/addGmsh.cmake index 897195819..39cecb6e8 100644 --- a/cmake/addGmsh.cmake +++ b/cmake/addGmsh.cmake @@ -19,15 +19,27 @@ IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) OPTION( USE_GMSH_SDK OFF ) IF( USE_GMSH_SDK ) LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) - IF( UNIX ) - IF(APPLE) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) - ELSE() - # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) - ENDIF() - ENDIF() - TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) + FIND_PACKAGE(PkgConfig REQUIRED) + FIND_LIBRARY(GMSH_LIBRARY + NAMES gmsh gmsh.4.12 + PATHS "$ENV{CONDA_PREFIX}/lib" "/opt/homebrew/lib" ) + # PATHS "/opt/homebrew/lib" ) + SET(GMSH_LIBRARIES ${GMSH_LIBRARY}) + + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS( + GMSH DEFAULT_MSG + GMSH_LIBRARIES + ) + + # SET(GMSH_LIBRARIES "$ENV{CONDA_PREFIX}/lib/libgmsh.so") + + TARGET_LINK_LIBRARIES( + ${PROJECT_NAME} + PUBLIC + ${GMSH_LIBRARIES} + ) + MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) ELSE() MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) diff --git a/cmake/targetCompileDefs.cmake b/cmake/targetCompileDefs.cmake index f7c9ae517..b8c68788e 100644 --- a/cmake/targetCompileDefs.cmake +++ b/cmake/targetCompileDefs.cmake @@ -38,10 +38,10 @@ ENDIF() LIST( APPEND TARGET_COMPILE_DEF "-D${CMAKE_HOST_SYSTEM_NAME}_SYSTEM" ) #DEFINE DEBUG -IF( $ ) +IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug") LIST( APPEND TARGET_COMPILE_DEF "-DDEBUG_VER" ) ENDIF() #ADD TO PROJECT TARGET_COMPILE_DEFINITIONS( ${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_DEF} ) -MESSAGE( STATUS "COMPILE DEFINITIONS USED ARE ${TARGET_COMPILE_DEF}") \ No newline at end of file +MESSAGE( STATUS "COMPILE DEFINITIONS USED ARE ${TARGET_COMPILE_DEF}") diff --git a/cmake/targetLinkLibs.cmake b/cmake/targetLinkLibs.cmake index fb29a3ee5..024a1e8c1 100644 --- a/cmake/targetLinkLibs.cmake +++ b/cmake/targetLinkLibs.cmake @@ -16,49 +16,6 @@ # # -# Link libs to the project - -#.................................................................... -# -#.................................................................... - -FUNCTION(FIND_EASIFEM_DEPENDENCY EXT_PKG_LIST) - FOREACH(p ${EXT_PKG_LIST}) - FIND_PACKAGE( ${p} REQUIRED ) - IF( ${p}_FOUND ) - MESSAGE(STATUS "FOUND ${p}") - ELSE() - MESSAGE(ERROR "NOT FOUND ${p}") - ENDIF() - ENDFOREACH() -ENDFUNCTION(FIND_EASIFEM_DEPENDENCY) - -#.................................................................... -# -#.................................................................... - -FUNCTION(LINK_EASIFEM_DEPENDENCY EXT_PKG_LIST PROJECT_NAME) - FOREACH(p ${EXT_PKG_LIST}) - TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${p}::${p} ) - ENDFOREACH() -ENDFUNCTION(LINK_EASIFEM_DEPENDENCY) - -#.................................................................... -# -#.................................................................... - -IF( ${PROJECT_NAME} MATCHES "easifemBase" ) - IF( USE_LAPACK95 ) - LIST(APPEND EXT_PKGS LAPACK95) - LIST( APPEND TARGET_COMPILE_DEF "-DUSE_LAPACK95" ) - ENDIF() - - LIST(APPEND EXT_PKGS Sparsekit) - - FIND_EASIFEM_DEPENDENCY( "${EXT_PKGS}" ) - LINK_EASIFEM_DEPENDENCY( "${EXT_PKGS}" "${PROJECT_NAME}" ) -ENDIF() - #.................................................................... # #.................................................................... diff --git a/install.py b/install.py index c81816614..4e999f3d8 100755 --- a/install.py +++ b/install.py @@ -20,8 +20,8 @@ else: cmake_def = "" cmake_def += '-G "Ninja"' - cmake_def += " -D USE_GMSH_SDK:BOOL=OFF" - cmake_def += " -D CMAKE_BUILD_TYPE:STRING=Release" + cmake_def += " -D USE_GMSH_SDK:BOOL=ON" + cmake_def += " -D CMAKE_BUILD_TYPE=Debug" cmake_def += " -D BUILD_SHARED_LIBS:BOOL=ON" cmake_def += " -D CMAKE_INSTALL_PREFIX:PATH=${EASIFEM_CLASSES}" print("CMAKE DEF : ", cmake_def) diff --git a/src/modules/AbstractBC/CMakeLists.txt b/src/modules/AbstractBC/CMakeLists.txt index 47e087846..ebba19c43 100644 --- a/src/modules/AbstractBC/CMakeLists.txt +++ b/src/modules/AbstractBC/CMakeLists.txt @@ -1,5 +1,22 @@ +# 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}/AbstractBC_Class.F90 -) \ No newline at end of file +) diff --git a/src/modules/AbstractBC/src/AbstractBC.toml b/src/modules/AbstractBC/src/AbstractBC.toml new file mode 100644 index 000000000..5d7f409b5 --- /dev/null +++ b/src/modules/AbstractBC/src/AbstractBC.toml @@ -0,0 +1,61 @@ +[bc] +name="DirichletBC" +idof=1 +nodalValueType="Constant" # Time, SpaceTime, Space +useFunction=false +isNormal=false +isTangent=false +useExternal=false +value=20.0 # when nodalValueType=Constant +# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Space +# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Time +# value=[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]] # SpaceTime +spaceFunction="lua script f(x)" +timeFunction="lua script f(t)" +spaceTimeFunction="lua script f(x, t)" + +[bc.boundary] +isSelectionByMeshID = false +isSelectionByElemNum = false +isSelectionByBox = false +isSelectionByNodeNum = false + +[bc.boundary.meshID] +point = [1,2,3] # "filename.txt" +line = [1,2,3,4] # "filename.txt" +surface = [1,2,3] # "filename.txt" +volume = [1,2,3] # "filename.txt" + +[bc.boundary.box] +point = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +line = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +surface = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +volume = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +[bc.boundary.elemNum] +point = [1,2,3] +line = [1,2,3] +surface=[1,2,3] +volume=[1,2,3] + +[bc.boundary.nodeNum] +point = [1,2,3] +line = [1,2,3] +surface=[1,2,3] +volume=[1,2,3] + diff --git a/src/modules/AbstractBC/src/AbstractBC_Class.F90 b/src/modules/AbstractBC/src/AbstractBC_Class.F90 index a044df100..ca1e9526f 100644 --- a/src/modules/AbstractBC/src/AbstractBC_Class.F90 +++ b/src/modules/AbstractBC/src/AbstractBC_Class.F90 @@ -13,7 +13,6 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see -! MODULE AbstractBC_Class USE GlobalData @@ -24,9 +23,28 @@ MODULE AbstractBC_Class USE Domain_Class USE HDF5File_Class USE FPL, ONLY: ParameterList_ +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractBC_Class" +CHARACTER(*), PARAMETER :: default_name = "AbstractBC" +INTEGER(I4B), PARAMETER :: default_idof = 0_I4B +INTEGER(I4B), PARAMETER :: default_nodalValueType = -1_I4B +CHARACTER(*) , PARAMETER :: default_nodalValueType_char = "NONE" +LOGICAL(LGT), PARAMETER :: default_useFunction = .FALSE. +LOGICAL(LGT), PARAMETER :: default_isNormal = .FALSE. +LOGICAL(LGT), PARAMETER :: default_isTangent = .FALSE. +LOGICAL(LGT), PARAMETER :: default_useExternal = .FALSE. + +PUBLIC :: AbstractBC_ +PUBLIC :: AbstractBCPointer_ +PUBLIC :: AbstractBCDeallocate +PUBLIC :: AbstractBCcheckEssentialParam +PUBLIC :: SetAbstractBCParam +PUBLIC :: AbstractBCInitiate +PUBLIC :: AbstractBCImportFromToml +PUBLIC :: AbstractBCImportParamFromToml !---------------------------------------------------------------------------- ! AbstractBC_ @@ -38,23 +56,23 @@ MODULE AbstractBC_Class TYPE, ABSTRACT :: AbstractBC_ LOGICAL(LGT) :: isInitiated = .FALSE. - !! + !! It is true if the object is initiated TYPE(String) :: name !! name of boundary condition - INTEGER(I4B) :: idof = 0 + INTEGER(I4B) :: idof = default_idof !! degree of freedom number - INTEGER(I4B) :: nodalValueType = -1 + INTEGER(I4B) :: nodalValueType = default_nodalValueType !! Constant !! Space !! Time !! SpaceTime - LOGICAL(LGT) :: useFunction = .FALSE. + LOGICAL(LGT) :: useFunction = default_useFunction !! True if the boundary condition is analytical - LOGICAL(LGT) :: isNormal = .FALSE. + LOGICAL(LGT) :: isNormal = default_isNormal !! True if the boundary condition is normal to the boundary - LOGICAL(LGT) :: isTangent = .FALSE. + LOGICAL(LGT) :: isTangent = default_isTangent !! True if the boundary condition is tangent to the boundary - LOGICAL(LGT) :: useExternal = .FALSE. + LOGICAL(LGT) :: useExternal = default_useExternal !! if true then nodal values are used externally !! depending upon the context. !! Basically we do not use the nodal value stored in the @@ -77,25 +95,46 @@ MODULE AbstractBC_Class !! Domain CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => bc_Deallocate - PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID - PROCEDURE, PUBLIC, PASS(obj) :: Get => bc_Get - PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction - PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo - PROCEDURE, PUBLIC, PASS(obj) :: & - & CheckEssentialParam => bc_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & bc_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => bc_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => bc_Export PROCEDURE, PUBLIC, PASS(obj) :: Display => bc_Display - PROCEDURE, PUBLIC, PASS(obj) :: isUseFunction => bc_isUseFunction - !! Returns true if the useFunction is true + PROCEDURE, PASS(obj) :: ImportFromToml1 => bc_ImportFromToml1 + PROCEDURE, PASS(obj) :: ImportFromToml2 => bc_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & + & ImportFromToml2 + !! Import abstract kernel from toml + PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & + & bc_ImportParamFromToml + + ! SET: + ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: Set => bc_Set + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID + PROCEDURE, PUBLIC, PASS(obj) :: Get1 => bc_Get + PROCEDURE, PUBLIC, PASS(obj) :: Get2 => bc_GetFEVar + GENERIC, PUBLIC :: Get => Get1, Get2 + PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction + PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo PROCEDURE, PUBLIC, PASS(obj) :: GetQuery => bc_GetQuery + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => bc_GetQuery + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: isUseFunction => bc_isUseFunction + !! Returns true if the useFunction is true END TYPE AbstractBC_ -PUBLIC :: AbstractBC_ - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -104,72 +143,32 @@ MODULE AbstractBC_Class CLASS(AbstractBC_), POINTER :: ptr => NULL() END TYPE AbstractBCPointer_ -PUBLIC :: AbstractBCPointer_ - !---------------------------------------------------------------------------- ! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- -INTERFACE - MODULE SUBROUTINE bc_CheckEssentialParam(obj, param) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE bc_CheckEssentialParam -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(MeshSelection_), INTENT(IN) :: boundary - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - !> author: Vikas Sharma, Ph. D. -! date: 2023-02-12 -! summary: Deallocate data +! date: 2023-11-14 +! summary: Check essential parameters -INTERFACE - MODULE SUBROUTINE bc_Deallocate(obj) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - END SUBROUTINE bc_Deallocate -END INTERFACE - -INTERFACE AbstractBCDeallocate - MODULE PROCEDURE bc_Deallocate -END INTERFACE AbstractBCDeallocate - -PUBLIC :: AbstractBCDeallocate - -!---------------------------------------------------------------------------- -! AbstractBCcheckEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE AbstractBCcheckEssentialParam(obj, param, prefix) +INTERFACE AbstractBCcheckEssentialParam + MODULE SUBROUTINE bc_CheckEssentialParam(obj, param, prefix) CLASS(AbstractBC_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractBCcheckEssentialParam -END INTERFACE - -PUBLIC :: AbstractBCcheckEssentialParam + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE bc_CheckEssentialParam +END INTERFACE AbstractBCcheckEssentialParam !---------------------------------------------------------------------------- ! SetAbstractBCParam@ConstructorMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Set abstract boundary condition parameters + INTERFACE - MODULE SUBROUTINE setAbstractBCParam(param, prefix, & + MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & & name, idof, nodalValueType, useFunction, isNormal, isTangent, & & useExternal) TYPE(ParameterList_), INTENT(INOUT) :: param @@ -195,31 +194,48 @@ MODULE SUBROUTINE setAbstractBCParam(param, prefix, & !! default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useExternal !! default is false - END SUBROUTINE setAbstractBCParam + END SUBROUTINE SetAbstractBCParam END INTERFACE -PUBLIC :: setAbstractBCParam - !---------------------------------------------------------------------------- -! AbstractBCInitiate@ConstructorMethods +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- -INTERFACE - MODULE SUBROUTINE AbstractBCInitiate(obj, param, prefix, boundary, dom) +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Initiate abstract boundary condition + +INTERFACE AbstractBCInitiate + MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) CLASS(AbstractBC_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - CHARACTER(*), INTENT(IN) :: prefix TYPE(MeshSelection_), INTENT(IN) :: boundary CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE AbstractBCInitiate -END INTERFACE + END SUBROUTINE bc_Initiate +END INTERFACE AbstractBCInitiate -PUBLIC :: AbstractBCInitiate +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-02-12 +! summary: Deallocate data + +INTERFACE AbstractBCDeallocate + MODULE SUBROUTINE bc_Deallocate(obj) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + END SUBROUTINE bc_Deallocate +END INTERFACE AbstractBCDeallocate !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Import AbstractBC from HDF5File + INTERFACE MODULE SUBROUTINE bc_Import(obj, hdf5, group, dom) CLASS(AbstractBC_), INTENT(INOUT) :: obj @@ -245,6 +261,58 @@ MODULE SUBROUTINE bc_Export(obj, hdf5, group) END SUBROUTINE bc_Export END INTERFACE +!---------------------------------------------------------------------------- +! ImportParamFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param by reading the toml table + +INTERFACE AbstractBCImportParamFromToml + MODULE SUBROUTINE bc_ImportParamFromToml(obj, param, table) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE bc_ImportParamFromToml +END INTERFACE AbstractBCImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE AbstractBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + CLASS(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE bc_ImportFromToml1 +END INTERFACE AbstractBCImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE AbstractBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & + & filename, printToml) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + CLASS(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE bc_ImportFromToml2 +END INTERFACE AbstractBCImportFromToml + !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- @@ -294,6 +362,27 @@ MODULE SUBROUTINE bc_Get(obj, nodeNum, nodalValue, times) END SUBROUTINE bc_Get END INTERFACE +!---------------------------------------------------------------------------- +! Get@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-02-12 +! summary: Get the node number and nodal value + +INTERFACE + MODULE SUBROUTINE bc_GetFEVar(obj, fevar, globalNode, & + & spaceQuadPoints, timeQuadPoints, atime, timeVec) + CLASS(AbstractBC_), INTENT(IN) :: obj + TYPE(FEVariable_), INTENT(INOUT) :: fevar + INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceQuadPoints(:, :) + REAL(DFP), OPTIONAL, INTENT(IN) :: timeQuadPoints(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: atime + REAL(DFP), OPTIONAL, INTENT(IN) :: timeVec(:) + END SUBROUTINE bc_GetFEVar +END INTERFACE + !---------------------------------------------------------------------------- ! GetFromFunction@GetMethods !---------------------------------------------------------------------------- @@ -327,10 +416,10 @@ END FUNCTION bc_GetDOFNo !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_isUseFunction(obj) RESULT(ans) + MODULE PURE FUNCTION bc_IsUseFunction(obj) RESULT(ans) CLASS(AbstractBC_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION bc_isUseFunction + END FUNCTION bc_IsUseFunction END INTERFACE !---------------------------------------------------------------------------- @@ -338,20 +427,20 @@ END FUNCTION bc_isUseFunction !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE bc_Set(obj, ConstantNodalValue, SpaceNodalValue, & - & TimeNodalValue, SpaceTimeNodalValue, SpaceFunction, TimeFunction, & - & SpaceTimeFunction) + MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & + & timeNodalValue, spaceTimeNodalValue, spaceFunction, timeFunction, & + & spaceTimeFunction) CLASS(AbstractBC_), INTENT(INOUT) :: obj - REAL(DFP), OPTIONAL, INTENT(IN) :: ConstantNodalValue - REAL(DFP), OPTIONAL, INTENT(IN) :: SpaceNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: TimeNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: SpaceTimeNodalValue(:, :) + REAL(DFP), OPTIONAL, INTENT(IN) :: constantNodalValue + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) PROCEDURE(iface_SpaceTimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & SpaceTimeFunction + & spaceTimeFunction PROCEDURE(iface_SpaceFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & SpaceFunction + & spaceFunction PROCEDURE(iface_TimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & TimeFunction + & timeFunction END SUBROUTINE bc_Set END INTERFACE @@ -379,4 +468,19 @@ MODULE PURE SUBROUTINE bc_GetQuery(obj, isInitiated, & END SUBROUTINE bc_GetQuery END INTERFACE +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) + CLASS(AbstractBC_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bc_GetPrefix +END INTERFACE + END MODULE AbstractBC_Class diff --git a/src/modules/AbstractFE/src/AbstractFE_Class.F90 b/src/modules/AbstractFE/src/AbstractFE_Class.F90 index 0df6d4f3a..8f104c19b 100644 --- a/src/modules/AbstractFE/src/AbstractFE_Class.F90 +++ b/src/modules/AbstractFE/src/AbstractFE_Class.F90 @@ -766,7 +766,8 @@ MODULE SUBROUTINE fe_GetQuadraturePoints1(obj, quad, quadratureType, & !! GaussChebyshevRadau, GaussChebyshevRadauLeft !! GaussChebyshevRadauRight INTEGER(I4B), OPTIONAL, INTENT(IN) :: order(:) - !! Order of integrand, either order or nips should be present + !! Order of integrand + !! either the order or the nips should be present !! Both nips and order should not be present INTEGER(I4B), OPTIONAL, INTENT(IN) :: nips(:) !! Number of integration points required diff --git a/src/modules/DirichletBC/src/DirichletBC_Class.F90 b/src/modules/DirichletBC/src/DirichletBC_Class.F90 index 4d5f424d7..ad35bf899 100644 --- a/src/modules/DirichletBC/src/DirichletBC_Class.F90 +++ b/src/modules/DirichletBC/src/DirichletBC_Class.F90 @@ -22,6 +22,8 @@ MODULE DirichletBC_Class USE Domain_Class, ONLY: Domain_ USE FPL, ONLY: ParameterList_ USE AbstractBC_Class +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "DirichletBC_Class" @@ -31,6 +33,7 @@ MODULE DirichletBC_Class PUBLIC :: DirichletBCPointer_ PUBLIC :: AddDirichletBC PUBLIC :: GetDirichletBCPointer +PUBLIC :: DirichletBCImportFromToml !---------------------------------------------------------------------------- ! DirichletBC_ @@ -43,9 +46,7 @@ MODULE DirichletBC_Class TYPE, EXTENDS(AbstractBC_) :: DirichletBC_ CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & - & bc_checkEssentialParam - PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix FINAL :: bc_Final END TYPE DirichletBC_ @@ -85,53 +86,6 @@ MODULE SUBROUTINE bc_Deallocate_Ptr_Vector(obj) END SUBROUTINE bc_Deallocate_Ptr_Vector END INTERFACE DEALLOCATE -!---------------------------------------------------------------------------- -! checkEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_checkEssentialParam(obj, param) - CLASS(DirichletBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE bc_checkEssentialParam -END INTERFACE - -!---------------------------------------------------------------------------- -! setDirichletParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE SetDirichletBCParam(param, name, idof, nodalValueType, & - & useFunction, isNormal, isTangent) - TYPE(ParameterList_), INTENT(INOUT) :: param - CHARACTER(*), INTENT(IN) :: name - INTEGER(I4B), INTENT(IN) :: idof - INTEGER(I4B), INTENT(IN) :: nodalValueType - !! Space - !! Time - !! SpaceTime - !! Constant - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTangent - END SUBROUTINE SetDirichletBCParam -END INTERFACE - -PUBLIC :: SetDirichletBCParam - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) - CLASS(DirichletBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(MeshSelection_), INTENT(IN) :: boundary - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -183,6 +137,61 @@ MODULE FUNCTION bc_GetDirichletBCPointer(dbc, dbcNo) RESULT(ans) END FUNCTION bc_GetDirichletBCPointer END INTERFACE GetDirichletBCPointer +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Get the prefix + +INTERFACE + MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) + CLASS(DirichletBC_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bc_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE DirichletBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom, tomlName) + TYPE(DirichletBCPointer_), INTENT(INOUT) :: obj(:) + !! Should be allocated outside + TYPE(toml_table), INTENT(INOUT) :: table + !! Toml table to returned + CLASS(Domain_), TARGET, INTENT(IN) :: dom + !! domain + CHARACTER(*), INTENT(IN) :: tomlName + END SUBROUTINE bc_ImportFromToml1 +END INTERFACE DirichletBCImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE DirichletBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & + & filename, printToml) + TYPE(DirichletBCPointer_), INTENT(INOUT) :: obj(:) + CLASS(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE bc_ImportFromToml2 +END INTERFACE DirichletBCImportFromToml + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/modules/Fhash/CMakeLists.txt b/src/modules/Fhash/CMakeLists.txt new file mode 100644 index 000000000..26f0a3426 --- /dev/null +++ b/src/modules/Fhash/CMakeLists.txt @@ -0,0 +1,19 @@ +# This program is taken from +# https://github.com/LKedward/fhash + +SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +TARGET_SOURCES( + ${PROJECT_NAME} PRIVATE + ${src_path}/fhash.F90 + ${src_path}/fhash_sll.F90 + ${src_path}/fhash_data_container.F90 + ${src_path}/fhash_tbl.F90 + ${src_path}/fhash_tbl_iter.F90 + ${src_path}/fhash_fnv.F90 + ${src_path}/fhash_key/base.F90 + ${src_path}/fhash_key/int32.F90 + ${src_path}/fhash_key/int64.F90 + ${src_path}/fhash_key/char.F90 + ${src_path}/fhash_key/int32_1d.F90 + ${src_path}/fhash_key/int64_1d.F90 +) diff --git a/src/modules/Fhash/src/fhash.F90 b/src/modules/Fhash/src/fhash.F90 new file mode 100644 index 000000000..20092465a --- /dev/null +++ b/src/modules/Fhash/src/fhash.F90 @@ -0,0 +1,14 @@ +! fhash module is taken from +! https://github.com/LKedward/fhash + +MODULE fhash +USE fhash_tbl, ONLY: fhash_tbl_t +USE fhash_tbl_iter, ONLY: fhash_iter_t +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_key_char, ONLY: fhash_key_char_t, fhash_key +USE fhash_key_int32, ONLY: fhash_key_int32_t, fhash_key +USE fhash_key_int64, ONLY: fhash_key_int64_t, fhash_key +USE fhash_key_int32_1d, ONLY: fhash_key_int32_1d_t, fhash_key +USE fhash_key_int64_1d, ONLY: fhash_key_int64_1d_t, fhash_key +IMPLICIT NONE +END MODULE fhash diff --git a/src/modules/Fhash/src/fhash_data_container.F90 b/src/modules/Fhash/src/fhash_data_container.F90 new file mode 100644 index 000000000..41fdaac69 --- /dev/null +++ b/src/modules/Fhash/src/fhash_data_container.F90 @@ -0,0 +1,241 @@ +! This library is taken from +! https://github.com/LKedward/fhash +!> Implements simple container type +!> for polymorphic scalars and 1D arrays +MODULE fhash_data_container +USE ISO_FORTRAN_ENV, ONLY: sp => REAL32, dp => REAL64, INT32, INT64 +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_container_t +PUBLIC fhash_container + +!> Generic container for scalar and 1D data +TYPE fhash_container_t + + CLASS(*), ALLOCATABLE :: scalar_data + CLASS(*), POINTER :: scalar_ptr => NULL() + +CONTAINS + + PROCEDURE :: allocated => fhash_container_allocated + PROCEDURE :: get => fhash_container_get_scalar + PROCEDURE :: get_ptr => fhash_container_get_scalar_ptr + +END TYPE fhash_container_t + +!> Create a fhash_container object from a polymorphic value +INTERFACE fhash_container + MODULE PROCEDURE fhash_container_scalar +END INTERFACE fhash_container + +CONTAINS + +!> Helper to initialise a polymorphic data container with scalar +FUNCTION fhash_container_scalar(VALUE, POINTER) RESULT(container) + + !> Value to store + CLASS(*), INTENT(in), TARGET :: VALUE + + !> If .true., store pointer to value instead of copying + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + TYPE(fhash_container_t) :: container + + IF (PRESENT(POINTER)) THEN + IF (POINTER) THEN + container%scalar_ptr => VALUE + ELSE + IF (ALLOCATED(container%scalar_data)) DEALLOCATE (container%scalar_data) + ALLOCATE (container%scalar_data, source=VALUE) + END IF + ELSE + IF (ALLOCATED(container%scalar_data)) DEALLOCATE (container%scalar_data) + ALLOCATE (container%scalar_data, source=VALUE) + END IF + +END FUNCTION fhash_container_scalar + +!> Helper to determine if container contains anything +FUNCTION fhash_container_allocated(container) RESULT(alloc) + CLASS(fhash_container_t), INTENT(in) :: container + LOGICAL :: alloc + + alloc = ALLOCATED(container%scalar_data) .OR. & + ASSOCIATED(container%scalar_ptr) + +END FUNCTION fhash_container_allocated + +!> Helper to return container value as intrinsic type + subroutine fhash_container_get_scalar(container,i32,i64,r32,r64,char,bool,raw,match,type_string) + CLASS(fhash_container_t), INTENT(in), TARGET :: container + INTEGER(INT32), INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), INTENT(out), OPTIONAL :: i64 + REAL(sp), INTENT(out), OPTIONAL :: r32 + REAL(dp), INTENT(out), OPTIONAL :: r64 + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: char + LOGICAL, INTENT(out), OPTIONAL :: bool + CLASS(*), ALLOCATABLE, INTENT(out), OPTIONAL :: raw + LOGICAL, INTENT(out), OPTIONAL :: match + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: type_string + + CLASS(*), POINTER :: DATA + + IF (PRESENT(match)) match = .FALSE. + + IF (.NOT. container%ALLOCATED()) RETURN + + IF (ALLOCATED(container%scalar_data)) THEN + DATA => container%scalar_data + ELSE + DATA => container%scalar_ptr + END IF + + IF (PRESENT(raw)) THEN + IF (PRESENT(match)) match = .TRUE. + ALLOCATE (raw, source=DATA) + END IF + + SELECT TYPE (d => DATA) + TYPE is (INTEGER(INT32)) + IF (PRESENT(type_string)) type_string = 'integer32' + IF (PRESENT(i32)) THEN + IF (PRESENT(match)) match = .TRUE. + i32 = d + RETURN + END IF + + TYPE is (INTEGER(INT64)) + IF (PRESENT(type_string)) type_string = 'integer64' + IF (PRESENT(i64)) THEN + IF (PRESENT(match)) match = .TRUE. + i64 = d + RETURN + END IF + + TYPE is (REAL(sp)) + IF (PRESENT(type_string)) type_string = 'real32' + IF (PRESENT(r32)) THEN + IF (PRESENT(match)) match = .TRUE. + r32 = d + RETURN + END IF + + TYPE is (REAL(dp)) + IF (PRESENT(type_string)) type_string = 'real64' + IF (PRESENT(r64)) THEN + IF (PRESENT(match)) match = .TRUE. + r64 = d + RETURN + END IF + + TYPE is (CHARACTER(*)) + IF (PRESENT(type_string)) type_string = 'character*' + IF (PRESENT(char)) THEN + IF (PRESENT(match)) match = .TRUE. + char = d + RETURN + END IF + + TYPE is (LOGICAL) + IF (PRESENT(type_string)) type_string = 'logical' + IF (PRESENT(bool)) THEN + IF (PRESENT(match)) match = .TRUE. + bool = d + RETURN + END IF + + CLASS default + IF (PRESENT(type_string)) type_string = 'unknown' + + END SELECT + +END SUBROUTINE fhash_container_get_scalar + +!> Helper to return pointer to container value as intrinsic type + subroutine fhash_container_get_scalar_ptr(container,i32,i64,r32,r64,char,bool,raw,match,type_string) + CLASS(fhash_container_t), INTENT(in), TARGET :: container + INTEGER(INT32), POINTER, INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), POINTER, INTENT(out), OPTIONAL :: i64 + REAL(sp), POINTER, INTENT(out), OPTIONAL :: r32 + REAL(dp), POINTER, INTENT(out), OPTIONAL :: r64 + CHARACTER(:), POINTER, INTENT(out), OPTIONAL :: char + LOGICAL, POINTER, INTENT(out), OPTIONAL :: bool + CLASS(*), POINTER, INTENT(out), OPTIONAL :: raw + LOGICAL, INTENT(out), OPTIONAL :: match + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: type_string + + CLASS(*), POINTER :: DATA + + IF (PRESENT(match)) match = .FALSE. + + IF (.NOT. container%ALLOCATED()) RETURN + + IF (ALLOCATED(container%scalar_data)) THEN + DATA => container%scalar_data + ELSE + DATA => container%scalar_ptr + END IF + + IF (PRESENT(raw)) THEN + IF (PRESENT(match)) match = .TRUE. + raw => DATA + END IF + + SELECT TYPE (d => DATA) + TYPE is (INTEGER(INT32)) + IF (PRESENT(i32)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'integer32' + i32 => d + RETURN + END IF + + TYPE is (INTEGER(INT64)) + IF (PRESENT(i64)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'integer64' + i64 => d + RETURN + END IF + + TYPE is (REAL(sp)) + IF (PRESENT(r32)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'real32' + r32 => d + RETURN + END IF + + TYPE is (REAL(dp)) + IF (PRESENT(r64)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'real64' + r64 => d + RETURN + END IF + + TYPE is (CHARACTER(*)) + IF (PRESENT(char)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'character*' + char => d + RETURN + END IF + + TYPE is (LOGICAL) + IF (PRESENT(bool)) THEN + IF (PRESENT(match)) match = .TRUE. + IF (PRESENT(type_string)) type_string = 'logical' + bool => d + RETURN + END IF + + CLASS DEFAULT + IF (PRESENT(type_string)) type_string = 'unknown' + + END SELECT + +END SUBROUTINE fhash_container_get_scalar_ptr + +END MODULE fhash_data_container diff --git a/src/modules/Fhash/src/fhash_fnv.F90 b/src/modules/Fhash/src/fhash_fnv.F90 new file mode 100644 index 000000000..1bd04b5b7 --- /dev/null +++ b/src/modules/Fhash/src/fhash_fnv.F90 @@ -0,0 +1,181 @@ +!> A module for Fowler–Noll–Vo (FNV) hashing +!> +!> Implements the FNV 1a algorithm for 32bit hashes +!> +!> Supports hashing of: +!> - 32bit integers (scalar & 1D array) +!> - 64bit integers (scalar & 1D array) +!> - character(*), default kind +!> +!> The lack of unsigned arithmetic in Fortran means that +!> 64bit arithmetic is needed to perform 32bit hashing. +!> Hashes are therefore returned as int64. +!> +MODULE fhash_fnv +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE ISO_C_BINDING, ONLY: C_CHAR +IMPLICIT NONE + +PRIVATE +PUBLIC :: fnv_1a, hash_string + +!> Starting seed +INTEGER(INT64), PARAMETER :: FNV_OFFSET_32 = 2166136261_INT64 + +!> Hashing prime +INTEGER(INT64), PARAMETER :: FNV_PRIME_32 = 16777619_INT64 + +!> Generic interface to perform hashing +!> +!> Usage: +!>```fortran +!> fnv_1a([seed],input) +!>``` +!> where `input` is any of the supported types +INTERFACE fnv_1a + MODULE PROCEDURE fnv_1a_char_scalar + MODULE PROCEDURE fnv_1a_char_scalar_seed + MODULE PROCEDURE fnv_1a_int32_scalar + MODULE PROCEDURE fnv_1a_int32_scalar_seed + MODULE PROCEDURE fnv_1a_int32_1d + MODULE PROCEDURE fnv_1a_int32_1d_seed + MODULE PROCEDURE fnv_1a_int64_scalar + MODULE PROCEDURE fnv_1a_int64_scalar_seed + MODULE PROCEDURE fnv_1a_int64_1d + MODULE PROCEDURE fnv_1a_int64_1d_seed +END INTERFACE fnv_1a + +CONTAINS + +!> Hash a single default kind character variable +PURE FUNCTION fnv_1a_char_scalar(input) RESULT(hash) + CHARACTER(*), INTENT(in) :: input + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_char_scalar + +!> Hash a character(*) string of default kind +PURE FUNCTION fnv_1a_char_scalar_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + CHARACTER(*), INTENT(in) :: input + INTEGER(INT64) :: hash + + INTEGER :: i + INTEGER(INT64) :: item + + hash = seed + + DO i = 1, LEN(input) + item = TRANSFER([IACHAR(input(i:i), INT32), 0_INT32], item) + hash = IEOR(hash, item) * fnv_prime_32 + END DO + +END FUNCTION fnv_1a_char_scalar_seed + +!> Hash a single 32bit integer +PURE FUNCTION fnv_1a_int32_scalar(input) RESULT(hash) + INTEGER(INT32), INTENT(in) :: input + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int32_scalar + +!> Hash a single 32bit integer with a starting seed +PURE FUNCTION fnv_1a_int32_scalar_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT32), INTENT(in) :: input + INTEGER(INT64) :: hash + + CHARACTER(len=4, kind=C_CHAR) :: chars + + chars = TRANSFER(input, chars) + + hash = fnv_1a(seed, chars) + +END FUNCTION fnv_1a_int32_scalar_seed + +!> Hash a 1D array of 32bit integers +PURE FUNCTION fnv_1a_int32_1d(input) RESULT(hash) + INTEGER(INT32), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int32_1d + +!> Hash a 1D array of 32bit integers with a starting seed +PURE FUNCTION fnv_1a_int32_1d_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT32), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + INTEGER :: i + + hash = seed + DO i = 1, SIZE(input) + hash = fnv_1a(hash, input(i)) + END DO + +END FUNCTION fnv_1a_int32_1d_seed + +!> Hash a single 64bit integer +PURE FUNCTION fnv_1a_int64_scalar(input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: input + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int64_scalar + +!> Hash a single 64bit integer with a starting seed +PURE FUNCTION fnv_1a_int64_scalar_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT64), INTENT(in) :: input + INTEGER(INT64) :: hash + + CHARACTER(len=8, kind=C_CHAR) :: chars + + chars = TRANSFER(input, chars) + + hash = fnv_1a(seed, chars) + +END FUNCTION fnv_1a_int64_scalar_seed + +!> Hash a 1D array of 64bit integers +PURE FUNCTION fnv_1a_int64_1d(input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + hash = fnv_1a(FNV_OFFSET_32, input) + +END FUNCTION fnv_1a_int64_1d + +!> Hash a 1D array of 64bit integers with a starting seed +PURE FUNCTION fnv_1a_int64_1d_seed(seed, input) RESULT(hash) + INTEGER(INT64), INTENT(in) :: seed + INTEGER(INT64), INTENT(in) :: input(:) + INTEGER(INT64) :: hash + + INTEGER :: i + + hash = seed + DO i = 1, SIZE(input) + hash = fnv_1a(hash, input(i)) + END DO + +END FUNCTION fnv_1a_int64_1d_seed + +!> Help fcn to convert hash to hex representation +FUNCTION hash_string(hash_value) RESULT(str) + INTEGER(INT64), INTENT(in) :: hash_value + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(len=10) :: str) + WRITE (str, '(Z0)') INT(hash_value, INT32) + +END FUNCTION hash_string + +END MODULE fhash_fnv diff --git a/src/modules/Fhash/src/fhash_key/base.F90 b/src/modules/Fhash/src/fhash_key/base.F90 new file mode 100644 index 000000000..e7537bdec --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/base.F90 @@ -0,0 +1,42 @@ +!> Implements an abstract type for hash keys +!> +MODULE fhash_key_base +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_t + +!> Abstract base type for defining hash keys +TYPE, ABSTRACT :: fhash_key_t +CONTAINS + PROCEDURE(hash_proc), DEFERRED :: hash + PROCEDURE(equality_proc), DEFERRED :: equals + PROCEDURE(to_string_proc), DEFERRED :: to_string + GENERIC, PUBLIC :: OPERATOR(==) => equals +END TYPE fhash_key_t + +ABSTRACT INTERFACE + + PURE FUNCTION equality_proc(key1, key2) RESULT(keys_equal) + IMPORT + CLASS(fhash_key_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + END FUNCTION equality_proc + + PURE FUNCTION hash_proc(key) RESULT(hash) + IMPORT + CLASS(fhash_key_t), INTENT(in) :: key + INTEGER(INT64) :: hash + END FUNCTION hash_proc + + FUNCTION to_string_proc(key) RESULT(str) + IMPORT + CLASS(fhash_key_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + END FUNCTION to_string_proc + +END INTERFACE + +END MODULE fhash_key_base diff --git a/src/modules/Fhash/src/fhash_key/char.F90 b/src/modules/Fhash/src/fhash_key/char.F90 new file mode 100644 index 000000000..63f1a90e9 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/char.F90 @@ -0,0 +1,76 @@ +!> Implements a concrete type for scalar int32 hash keys +!> +MODULE fhash_key_char +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_char_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_char_t + PRIVATE + CHARACTER(:), ALLOCATABLE :: VALUE +CONTAINS + PROCEDURE, PASS :: hash => key_hash_char + PROCEDURE, PASS :: equals => key_equal_char + PROCEDURE, PASS :: to_string => key_char_to_string +END TYPE fhash_key_char_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_char +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_char(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_char_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_char_t) + IF (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE)) THEN + IF (key1%VALUE == k2%VALUE) THEN + keys_equal = .TRUE. + RETURN + END IF + END IF + END SELECT + +END FUNCTION key_equal_char + +!> Generate hash of key +PURE FUNCTION key_hash_char(key) RESULT(hash) + CLASS(fhash_key_char_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_char + +!> Generate string representation of hash +FUNCTION key_char_to_string(key) RESULT(str) + CLASS(fhash_key_char_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + str = key%VALUE + +END FUNCTION key_char_to_string + +!> Create new key container from a scalar int32 +FUNCTION key_from_char(source) RESULT(key) + CHARACTER(*), INTENT(in) :: source + TYPE(fhash_key_char_t) :: key + + key%VALUE = source + +END FUNCTION key_from_char + +END MODULE fhash_key_char diff --git a/src/modules/Fhash/src/fhash_key/int32.F90 b/src/modules/Fhash/src/fhash_key/int32.F90 new file mode 100644 index 000000000..0d3fac8e2 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int32.F90 @@ -0,0 +1,76 @@ +!> Implements a concrete type for scalar int32 hash keys +!> +MODULE fhash_key_int32 +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int32_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int32_t + PRIVATE + INTEGER(INT32) :: VALUE +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int32 + PROCEDURE, PASS :: equals => key_equal_int32 + PROCEDURE, PASS :: to_string => key_int32_to_string +END TYPE fhash_key_int32_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int32 +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int32(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int32_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int32_t) + IF (key1%VALUE == k2%VALUE) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int32 + +!> Generate hash of key +PURE FUNCTION key_hash_int32(key) RESULT(hash) + CLASS(fhash_key_int32_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int32 + +!> Generate string representation of hash +PURE FUNCTION key_int32_to_string(key) RESULT(str) + CLASS(fhash_key_int32_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int32_to_string + +!> Create new key container from a scalar int32 +FUNCTION key_from_int32(source) RESULT(key) + INTEGER(INT32), INTENT(in) :: source + TYPE(fhash_key_int32_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int32 + +END MODULE fhash_key_int32 diff --git a/src/modules/Fhash/src/fhash_key/int32_1d.F90 b/src/modules/Fhash/src/fhash_key/int32_1d.F90 new file mode 100644 index 000000000..78c0123e5 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int32_1d.F90 @@ -0,0 +1,82 @@ +!> Implements a concrete type for 1D int32 array hash keys +!> +MODULE fhash_key_int32_1d +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int32_1d_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int32_1d_t + PRIVATE + INTEGER(INT32), ALLOCATABLE :: VALUE(:) +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int32_1d + PROCEDURE, PASS :: equals => key_equal_int32_1d + PROCEDURE, PASS :: to_string => key_int32_1d_to_string +END TYPE fhash_key_int32_1d_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int32_1d +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int32_1d(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int32_1d_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int32_1d_t) + IF (.NOT. (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE))) THEN + RETURN + END IF + IF (SIZE(key1%VALUE) /= SIZE(k2%VALUE)) THEN + RETURN + END IF + IF (ALL(key1%VALUE == k2%VALUE)) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int32_1d + +!> Generate hash of key +PURE FUNCTION key_hash_int32_1d(key) RESULT(hash) + CLASS(fhash_key_int32_1d_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int32_1d + +!> Generate string representation of hash +PURE FUNCTION key_int32_1d_to_string(key) RESULT(str) + CLASS(fhash_key_int32_1d_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int32_1d_to_string + +!> Create new key container from a scalar int32 +FUNCTION key_from_int32_1d(source) RESULT(key) + INTEGER(INT32), INTENT(in) :: source(:) + TYPE(fhash_key_int32_1d_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int32_1d + +END MODULE fhash_key_int32_1d diff --git a/src/modules/Fhash/src/fhash_key/int64.F90 b/src/modules/Fhash/src/fhash_key/int64.F90 new file mode 100644 index 000000000..a4b5e18d2 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int64.F90 @@ -0,0 +1,76 @@ +!> Implements a concrete type for scalar int64 hash keys +!> +MODULE fhash_key_int64 +USE ISO_FORTRAN_ENV, ONLY: INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int64_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int64_t + PRIVATE + INTEGER(INT64) :: VALUE +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int64 + PROCEDURE, PASS :: equals => key_equal_int64 + PROCEDURE, PASS :: to_string => key_int64_to_string +END TYPE fhash_key_int64_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int64 +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int64(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int64_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int64_t) + IF (key1%VALUE == k2%VALUE) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int64 + +!> Generate hash of key +PURE FUNCTION key_hash_int64(key) RESULT(hash) + CLASS(fhash_key_int64_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int64 + +!> Generate string representation of hash +PURE FUNCTION key_int64_to_string(key) RESULT(str) + CLASS(fhash_key_int64_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int64_to_string + +!> Create new key container from a scalar int64 +FUNCTION key_from_int64(source) RESULT(key) + INTEGER(INT64), INTENT(in) :: source + TYPE(fhash_key_int64_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int64 + +END MODULE fhash_key_int64 diff --git a/src/modules/Fhash/src/fhash_key/int64_1d.F90 b/src/modules/Fhash/src/fhash_key/int64_1d.F90 new file mode 100644 index 000000000..2c2c2ccd8 --- /dev/null +++ b/src/modules/Fhash/src/fhash_key/int64_1d.F90 @@ -0,0 +1,82 @@ +!> Implements a concrete type for 1D int64 array hash keys +!> +MODULE fhash_key_int64_1d +USE ISO_FORTRAN_ENV, ONLY: INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_fnv, ONLY: fnv_1a +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_key_int64_1d_t +PUBLIC fhash_key + +!> Hash table key container +TYPE, EXTENDS(fhash_key_t) :: fhash_key_int64_1d_t + PRIVATE + INTEGER(INT64), ALLOCATABLE :: VALUE(:) +CONTAINS + PROCEDURE, PASS :: hash => key_hash_int64_1d + PROCEDURE, PASS :: equals => key_equal_int64_1d + PROCEDURE, PASS :: to_string => key_int64_1d_to_string +END TYPE fhash_key_int64_1d_t + +INTERFACE fhash_key + MODULE PROCEDURE :: key_from_int64_1d +END INTERFACE fhash_key + +CONTAINS + +!> Check if two keys are equal +PURE FUNCTION key_equal_int64_1d(key1, key2) RESULT(keys_equal) + CLASS(fhash_key_int64_1d_t), INTENT(in) :: key1 + CLASS(fhash_key_t), INTENT(in) :: key2 + LOGICAL :: keys_equal + + keys_equal = .FALSE. + + SELECT TYPE (k2 => key2) + TYPE is (fhash_key_int64_1d_t) + IF (.NOT. (ALLOCATED(key1%VALUE) .AND. ALLOCATED(k2%VALUE))) THEN + RETURN + END IF + IF (SIZE(key1%VALUE) /= SIZE(k2%VALUE)) THEN + RETURN + END IF + IF (ALL(key1%VALUE == k2%VALUE)) THEN + keys_equal = .TRUE. + RETURN + END IF + END SELECT + +END FUNCTION key_equal_int64_1d + +!> Generate hash of key +PURE FUNCTION key_hash_int64_1d(key) RESULT(hash) + CLASS(fhash_key_int64_1d_t), INTENT(in) :: key + INTEGER(INT64) :: hash + + hash = fnv_1a(key%VALUE) + +END FUNCTION key_hash_int64_1d + +!> Generate string representation of hash +PURE FUNCTION key_int64_1d_to_string(key) RESULT(str) + CLASS(fhash_key_int64_1d_t), INTENT(in) :: key + CHARACTER(:), ALLOCATABLE :: str + + ALLOCATE (CHARACTER(1024) :: str) + WRITE (str, *) key%VALUE + str = TRIM(str) + +END FUNCTION key_int64_1d_to_string + +!> Create new key container from a scalar int64 +FUNCTION key_from_int64_1d(source) RESULT(key) + INTEGER(INT64), INTENT(in) :: source(:) + TYPE(fhash_key_int64_1d_t) :: key + + key%VALUE = source + +END FUNCTION key_from_int64_1d + +END MODULE fhash_key_int64_1d diff --git a/src/modules/Fhash/src/fhash_sll.F90 b/src/modules/Fhash/src/fhash_sll.F90 new file mode 100644 index 000000000..c9aec1190 --- /dev/null +++ b/src/modules/Fhash/src/fhash_sll.F90 @@ -0,0 +1,277 @@ +!> Implements singly-linked list (sll) node with generic data container +!> +MODULE fhash_sll +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64 +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_data_container, ONLY: fhash_container_t +IMPLICIT NONE + +!> Node type for hash table singly linked list +TYPE fhash_node_t + + CLASS(fhash_key_t), ALLOCATABLE :: key + TYPE(fhash_container_t) :: VALUE + TYPE(fhash_node_t), POINTER :: next => NULL() + +END TYPE fhash_node_t + +CONTAINS + +!> Append node to SLL +RECURSIVE SUBROUTINE sll_push_node(node, key, VALUE, POINTER) + + !> Node to which to add data + TYPE(fhash_node_t), INTENT(inout) :: node + + !> Key to add + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value to add + CLASS(*), INTENT(in), TARGET :: VALUE + + !> Store only a point if .true. + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + IF (ALLOCATED(node%key)) THEN + + IF (node%key == key) THEN + + CALL sll_node_set(node, VALUE, POINTER) + RETURN + + END IF + + IF (.NOT. ASSOCIATED(node%next)) THEN + ALLOCATE (node%next) + END IF + + CALL sll_push_node(node%next, key, VALUE, POINTER) + + ELSE + + node%key = key + CALL sll_node_set(node, VALUE, POINTER) + + END IF + +END SUBROUTINE sll_push_node + +!> Set container value in node +!> +SUBROUTINE sll_node_set(node, VALUE, POINTER) + + !> Node to which to add data + TYPE(fhash_node_t), INTENT(inout) :: node + + !> Value to set + CLASS(*), INTENT(in), TARGET :: VALUE + + !> Store only a pointer if .true. + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + IF (PRESENT(POINTER)) THEN + IF (POINTER) THEN + node%VALUE%scalar_ptr => VALUE + RETURN + END IF + END IF + + IF (ALLOCATED(node%VALUE%scalar_data)) DEALLOCATE (node%VALUE%scalar_data) + ALLOCATE (node%VALUE%scalar_data, source=VALUE) + +END SUBROUTINE sll_node_set + +!> Search for a node with a specific key. +!> Returns a pointer to the 'data' component of the corresponding node. +!> Pointer is not associated if node cannot be found +RECURSIVE SUBROUTINE sll_find_in(node, key, DATA, found) + + !> Node to search in + TYPE(fhash_node_t), INTENT(in), TARGET :: node + + !> Key to look for + CLASS(fhash_key_t) :: key + + !> Pointer to value container if found. + !> (Unassociated if the key is not found in node) + TYPE(fhash_container_t), POINTER, INTENT(out) :: DATA + + LOGICAL, INTENT(out), OPTIONAL :: found + + DATA => NULL() + + IF (PRESENT(found)) found = .FALSE. + + IF (.NOT. ALLOCATED(node%key)) THEN + + RETURN + + ELSE IF (node%key == key) THEN + + IF (PRESENT(found)) found = .TRUE. + DATA => node%VALUE + RETURN + + ELSE IF (ASSOCIATED(node%next)) THEN + + CALL sll_find_in(node%next, key, DATA, found) + + END IF + +END SUBROUTINE sll_find_in + +!> Return a node at a specific depth in the sll +RECURSIVE SUBROUTINE sll_get_at(node, depth, key, DATA, found) + + !> Node to search in + TYPE(fhash_node_t), INTENT(in), TARGET :: node + + !> Node depth to access + INTEGER, INTENT(in) :: depth + + !> Key of found item + !> (Unallocated if no node is found at specified depth) + CLASS(fhash_key_t), INTENT(out), ALLOCATABLE :: key + + !> Pointer to value container if found. + !> (Unassociated if no node is found at specified depth) + TYPE(fhash_container_t), POINTER, INTENT(out) :: DATA + + LOGICAL, INTENT(out), OPTIONAL :: found + + DATA => NULL() + + IF (PRESENT(found)) found = .FALSE. + + IF (.NOT. ALLOCATED(node%key)) THEN + + RETURN + + ELSE IF (depth == 1) THEN + + IF (PRESENT(found)) found = .TRUE. + key = node%key + DATA => node%VALUE + RETURN + + ELSE IF (ASSOCIATED(node%next)) THEN + + CALL sll_get_at(node%next, depth - 1, key, DATA, found) + + END IF + +END SUBROUTINE sll_get_at + +!> Search for a node with a specific key and remove +RECURSIVE SUBROUTINE sll_remove(node, key, found, parent_node) + + !> Node to remove from + TYPE(fhash_node_t), INTENT(inout) :: node + + !> Key to remove + CLASS(fhash_key_t) :: key + + !> Indicates if the key was found in node and removed + LOGICAL, OPTIONAL, INTENT(out) :: found + + !> Used internally + TYPE(fhash_node_t), INTENT(inout), OPTIONAL :: parent_node + + TYPE(fhash_node_t), POINTER :: next_temp + + IF (PRESENT(found)) THEN + found = .FALSE. + END IF + + IF (.NOT. ALLOCATED(node%key)) THEN + + RETURN + + ELSE IF (node%key == key) THEN + + IF (PRESENT(found)) THEN + found = .TRUE. + END IF + + IF (.NOT. PRESENT(parent_node)) THEN + ! This is the top-level node + IF (ASSOCIATED(node%next)) THEN + ! Replace with next + next_temp => node%next + node = next_temp + DEALLOCATE (next_temp) + RETURN + ELSE + ! No children, just deallocate + DEALLOCATE (node%key) + RETURN + END IF + + ELSE + ! Not top-level node + IF (ASSOCIATED(node%next)) THEN + ! Join previous with next + next_temp => node%next + DEALLOCATE (parent_node%next) + parent_node%next => next_temp + RETURN + ELSE + ! No children, just deallocate + DEALLOCATE (node%key) + DEALLOCATE (parent_node%next) + RETURN + END IF + END IF + + ELSE IF (ASSOCIATED(node%next)) THEN + ! Look further down + CALL sll_remove(node%next, key, found, node) + + END IF + +END SUBROUTINE sll_remove + +!> Deallocate node components and those of its children +RECURSIVE SUBROUTINE sll_clean(node) + + !> Node to search in + TYPE(fhash_node_t), INTENT(inout) :: node + + IF (ASSOCIATED(node%next)) THEN + + CALL sll_clean(node%next) + DEALLOCATE (node%next) + + END IF + +END SUBROUTINE sll_clean + +!> Determine depth of SLL +FUNCTION node_depth(node) RESULT(depth) + + !> Node to check depth + TYPE(fhash_node_t), INTENT(in), TARGET :: node + + INTEGER :: depth + + TYPE(fhash_node_t), POINTER :: current + + IF (.NOT. ALLOCATED(node%key)) THEN + + depth = 0 + RETURN + + ELSE + + depth = 1 + current => node + DO WHILE (ASSOCIATED(current%next)) + depth = depth + 1 + current => current%next + END DO + + END IF + +END FUNCTION node_depth + +END MODULE fhash_sll diff --git a/src/modules/Fhash/src/fhash_tbl.F90 b/src/modules/Fhash/src/fhash_tbl.F90 new file mode 100644 index 000000000..a56527ac8 --- /dev/null +++ b/src/modules/Fhash/src/fhash_tbl.F90 @@ -0,0 +1,571 @@ +MODULE fhash_tbl +USE ISO_FORTRAN_ENV, ONLY: INT32, INT64, sp => REAL32, dp => REAL64 +USE fhash_data_container, ONLY: fhash_container +USE fhash_sll +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_tbl_t + +!> This condition should be unreachable by the public interface +INTEGER, PARAMETER, PUBLIC :: FHASH_INTERNAL_ERROR = -4 + +!> Error flag for operating on an unallocated table +INTEGER, PARAMETER, PUBLIC :: FHASH_EMPTY_TABLE = -3 + +!> Error flag for when retrieved data-type does not +!> match that expected by the invoked getter function +!> (`get_int32`,`get_int63`,`get_float`,'get_double`,`get_char`) +INTEGER, PARAMETER, PUBLIC :: FHASH_FOUND_WRONG_TYPE = -2 + +!> Error flag for when specified key is not found in the hash table +INTEGER, PARAMETER, PUBLIC :: FHASH_KEY_NOT_FOUND = -1 + +!> Default allocation size +INTEGER, PARAMETER :: FHASH_DEFAULT_ALLOCATION = 127 + +TYPE fhash_tbl_t + + TYPE(fhash_node_t), ALLOCATABLE :: buckets(:) + +CONTAINS + + PROCEDURE :: ALLOCATE => fhash_tbl_allocate + PROCEDURE :: unset => fhash_tbl_unset + PROCEDURE :: check_key => fhash_tbl_check_key + PROCEDURE :: stats => fhash_tbl_stats + + PROCEDURE :: fhash_tbl_set_scalar + GENERIC :: set => fhash_tbl_set_scalar + + PROCEDURE :: fhash_tbl_set_scalar_ptr + GENERIC :: set_ptr => fhash_tbl_set_scalar_ptr + + PROCEDURE :: fhash_tbl_get_int32, fhash_tbl_get_int64 + PROCEDURE :: fhash_tbl_get_float, fhash_tbl_get_double + PROCEDURE :: fhash_tbl_get_char, fhash_tbl_get_logical + PROCEDURE :: fhash_tbl_get_data, fhash_tbl_get_raw + + GENERIC :: get => fhash_tbl_get_int32, fhash_tbl_get_int64 + GENERIC :: get => fhash_tbl_get_float, fhash_tbl_get_double + GENERIC :: get => fhash_tbl_get_char, fhash_tbl_get_logical + GENERIC :: get => fhash_tbl_get_data + GENERIC :: get_raw => fhash_tbl_get_raw + + PROCEDURE :: fhash_tbl_get_int32_ptr, fhash_tbl_get_int64_ptr + PROCEDURE :: fhash_tbl_get_float_ptr, fhash_tbl_get_double_ptr + PROCEDURE :: fhash_tbl_get_char_ptr, fhash_tbl_get_logical_ptr + PROCEDURE :: fhash_tbl_get_raw_ptr + + GENERIC :: get_ptr => fhash_tbl_get_int32_ptr, fhash_tbl_get_int64_ptr + GENERIC :: get_ptr => fhash_tbl_get_float_ptr, fhash_tbl_get_double_ptr + GENERIC :: get_ptr => fhash_tbl_get_char_ptr, fhash_tbl_get_logical_ptr + GENERIC :: get_raw_ptr => fhash_tbl_get_raw_ptr + + FINAL :: fhash_tbl_cleanup + +END TYPE fhash_tbl_t + +CONTAINS + +!> Allocate hash table +SUBROUTINE fhash_tbl_allocate(tbl, size) + + !> Table object to allocate + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Number of buckets in hash table + !> If ommited, `tbl` is allocated with `FHASH_DEFAULT_ALLOCATION` + INTEGER, INTENT(in), OPTIONAL :: size + + IF (PRESENT(size)) THEN + ALLOCATE (tbl%buckets(size)) + ELSE + ALLOCATE (tbl%buckets(FHASH_DEFAULT_ALLOCATION)) + END IF + +END SUBROUTINE fhash_tbl_allocate + +!> Finalizer for fhash_tbl_t +SUBROUTINE fhash_tbl_cleanup(tbl) + + !> Table object to allocate + TYPE(fhash_tbl_t), INTENT(inout) :: tbl + + INTEGER :: i + + IF (.NOT. ALLOCATED(tbl%buckets)) RETURN + + DO i = 1, SIZE(tbl%buckets) + + CALL sll_clean(tbl%buckets(i)) + + END DO + +END SUBROUTINE fhash_tbl_cleanup + +!> Unset a value in the table +!> +SUBROUTINE fhash_tbl_unset(tbl, key, stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Key to remove + CLASS(fhash_key_t), INTENT(in) :: key + + !> Status flag. Zero if successful. + !> Unsuccessful: FHASH_EMPTY_TABLE | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + INTEGER :: index + LOGICAL :: found + + IF (PRESENT(stat)) stat = 0 + + IF (.NOT. ALLOCATED(tbl%buckets)) THEN + IF (PRESENT(stat)) stat = FHASH_EMPTY_TABLE + RETURN + END IF + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + CALL sll_remove(tbl%buckets(index), key, found) + + IF (PRESENT(stat)) stat = MERGE(0, FHASH_KEY_NOT_FOUND, found) + +END SUBROUTINE fhash_tbl_unset + +!> Check if key exists in table +SUBROUTINE fhash_tbl_check_key(tbl, key, stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Status flag. Zero if key is found. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out) :: stat + + INTEGER :: index + LOGICAL :: found + TYPE(fhash_container_t), POINTER :: DATA + + IF (.NOT. ALLOCATED(tbl%buckets)) THEN + stat = FHASH_EMPTY_TABLE + RETURN + END IF + + stat = 0 + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + + CALL sll_find_in(tbl%buckets(index), key, DATA, found) + + stat = MERGE(0, FHASH_KEY_NOT_FOUND, found) + + RETURN + +END SUBROUTINE fhash_tbl_check_key + +!> Get stats about the hash table +subroutine fhash_tbl_stats(tbl,num_buckets,num_items,num_collisions,max_depth) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Number of buckets allocated in table + INTEGER, INTENT(out), OPTIONAL :: num_buckets + + !> Number of key-value pairs stored in table + INTEGER, INTENT(out), OPTIONAL :: num_items + + !> Number of hash collisions + INTEGER, INTENT(out), OPTIONAL :: num_collisions + + !> Maximum depth of bucket in table + INTEGER, INTENT(out), OPTIONAL :: max_depth + + INTEGER :: i, depth + + ! Initialise stats + IF (PRESENT(num_items)) num_items = 0 + IF (PRESENT(num_collisions)) num_collisions = 0 + IF (PRESENT(max_depth)) max_depth = 0 + IF (PRESENT(num_buckets)) num_buckets = 0 + + IF (.NOT. ALLOCATED(tbl%buckets)) RETURN + + IF (PRESENT(num_buckets)) THEN + num_buckets = SIZE(tbl%buckets) + END IF + + DO i = 1, SIZE(tbl%buckets) + + depth = node_depth(tbl%buckets(i)) + + IF (PRESENT(num_items)) num_items = num_items + depth + + IF (PRESENT(num_collisions)) num_collisions = num_collisions + & + MERGE(depth - 1, 0, depth > 1) + + IF (PRESENT(max_depth)) max_depth = MAX(max_depth, depth) + + END DO + +END SUBROUTINE fhash_tbl_stats + +!> Set/update a polymorphic scalar value in the table +!> +!> `tbl` is allocated with default size if not already allocated +SUBROUTINE fhash_tbl_set_scalar(tbl, key, VALUE, POINTER) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Key to set/update + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value for key + CLASS(*), INTENT(in), TARGET :: VALUE + + !> If .true., store a pointer to value instead of copying + LOGICAL, INTENT(in), OPTIONAL :: POINTER + + INTEGER :: index + + IF (.NOT. ALLOCATED(tbl%buckets)) CALL fhash_tbl_allocate(tbl) + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + + CALL sll_push_node(tbl%buckets(index), key, VALUE, POINTER) + +END SUBROUTINE fhash_tbl_set_scalar + +!> Get wrapper routine for generic 'set_ptr' +!> +!> `tbl` is allocated with default size if not already allocated +SUBROUTINE fhash_tbl_set_scalar_ptr(tbl, key, VALUE) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(inout) :: tbl + + !> Key to set/update + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value for key + CLASS(*), INTENT(in), TARGET :: VALUE + + CALL fhash_tbl_set_scalar(tbl, key, VALUE, POINTER=.TRUE.) + +END SUBROUTINE fhash_tbl_set_scalar_ptr + +!> Retrieve data container from the hash table +SUBROUTINE fhash_tbl_get_data(tbl, key, DATA, stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Copy of value retrieved for key + TYPE(fhash_container_t), POINTER :: DATA + + !> Status flag. Zero if successful. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + INTEGER :: index + LOGICAL :: found + + IF (.NOT. ALLOCATED(tbl%buckets)) THEN + IF (PRESENT(stat)) stat = FHASH_EMPTY_TABLE + RETURN + END IF + + IF (PRESENT(stat)) stat = 0 + + index = MODULO(key%hash(), SIZE(tbl%buckets, kind=INT64)) + 1 + + CALL sll_find_in(tbl%buckets(index), key, DATA, found) + + IF (.NOT. found) THEN + + IF (PRESENT(stat)) stat = FHASH_KEY_NOT_FOUND + RETURN + + END IF + +END SUBROUTINE fhash_tbl_get_data + +!> Get wrapper to retrieve a scalar intrinsic type value +subroutine fhash_tbl_get_intrinsic_scalar(tbl,key,i32,i64,r32,r64,char,raw,bool,stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value to retrieve + INTEGER(INT32), INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), INTENT(out), OPTIONAL :: i64 + REAL(sp), INTENT(out), OPTIONAL :: r32 + REAL(dp), INTENT(out), OPTIONAL :: r64 + CHARACTER(:), ALLOCATABLE, INTENT(out), OPTIONAL :: char + LOGICAL, INTENT(out), OPTIONAL :: bool + CLASS(*), ALLOCATABLE, INTENT(out), OPTIONAL :: raw + + !> Status flag. Zero if successful. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | + !> `FHASH_FOUND_WRONG_TYPE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + LOGICAL :: type_match + INTEGER :: local_stat + TYPE(fhash_container_t), POINTER :: DATA + + CHARACTER(:), ALLOCATABLE :: char_temp + + IF (PRESENT(stat)) stat = 0 + + CALL fhash_tbl_get_data(tbl, key, DATA, local_stat) + + IF (local_stat /= 0) THEN + IF (PRESENT(stat)) stat = local_stat + RETURN + END IF + + IF (PRESENT(char)) THEN ! (Work-around for weird gfortran bug re char dummy) + + CALL DATA%get(i32, i64, r32, r64, char_temp, bool, raw, type_match) + + IF (type_match) char = char_temp + + ELSE + + CALL DATA%get(i32, i64, r32, r64, bool=bool, raw=raw, match=type_match) + + END IF + + IF (.NOT. type_match) THEN + IF (PRESENT(stat)) stat = FHASH_FOUND_WRONG_TYPE + RETURN + END IF + +END SUBROUTINE fhash_tbl_get_intrinsic_scalar + +!> Get wrapper to retrieve a scalar intrinsic type pointer +subroutine fhash_tbl_get_intrinsic_scalar_ptr(tbl,key,i32,i64,r32,r64,char,bool,raw,stat) + + !> Hash table object + CLASS(fhash_tbl_t), INTENT(in) :: tbl + + !> Key to retrieve + CLASS(fhash_key_t), INTENT(in) :: key + + !> Value to retrieve + INTEGER(INT32), POINTER, INTENT(out), OPTIONAL :: i32 + INTEGER(INT64), POINTER, INTENT(out), OPTIONAL :: i64 + REAL(sp), POINTER, INTENT(out), OPTIONAL :: r32 + REAL(dp), POINTER, INTENT(out), OPTIONAL :: r64 + CHARACTER(:), POINTER, INTENT(out), OPTIONAL :: char + LOGICAL, POINTER, INTENT(out), OPTIONAL :: bool + CLASS(*), POINTER, INTENT(out), OPTIONAL :: raw + + !> Status flag. Zero if successful. + !> Unsuccessful: `FHASH_EMPTY_TABLE` | + !> `FHASH_FOUND_WRONG_TYPE` | `FHASH_KEY_NOT_FOUND` + INTEGER, INTENT(out), OPTIONAL :: stat + + LOGICAL :: type_match + INTEGER :: local_stat + TYPE(fhash_container_t), POINTER :: DATA + + CHARACTER(:), POINTER :: char_temp + + IF (PRESENT(stat)) stat = 0 + + CALL fhash_tbl_get_data(tbl, key, DATA, local_stat) + + IF (local_stat /= 0) THEN + IF (PRESENT(stat)) stat = local_stat + RETURN + END IF + + IF (PRESENT(char)) THEN ! (Work-around for weird gfortran bug re char dummy) + + CALL DATA%get_ptr(i32, i64, r32, r64, char_temp, bool, raw, type_match) + + IF (type_match) char => char_temp + + ELSE + + CALL DATA%get_ptr(i32, i64, r32, r64, bool=bool, raw=raw, match=type_match) + + END IF + + IF (.NOT. type_match) THEN + IF (PRESENT(stat)) stat = FHASH_FOUND_WRONG_TYPE + RETURN + END IF + +END SUBROUTINE fhash_tbl_get_intrinsic_scalar_ptr + +!> Get wrapper to directly retrieve a scalar int32 value +SUBROUTINE fhash_tbl_get_int32(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT32), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, i32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int32 + +!> Get wrapper to directly retrieve a scalar int64 value +SUBROUTINE fhash_tbl_get_int64(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT64), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, i64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int64 + +!> Get wrapper to directly retrieve a scalar float value +SUBROUTINE fhash_tbl_get_float(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(sp), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, r32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_float + +!> Get wrapper to directly retrieve a scalar double value +SUBROUTINE fhash_tbl_get_double(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(dp), INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, r64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_double + +!> Get wrapper to directly retrieve a scalar character value +SUBROUTINE fhash_tbl_get_char(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CHARACTER(:), ALLOCATABLE, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, char=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_char + +!> Get wrapper to directly retrieve a scalar logical value +SUBROUTINE fhash_tbl_get_logical(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + LOGICAL, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, bool=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_logical + +!> Get wrapper to directly retrieve underlying polymorhpic scalar value +SUBROUTINE fhash_tbl_get_raw(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CLASS(*), ALLOCATABLE, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar(tbl, key, raw=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_raw + +!> Get wrapper to directly retrieve a scalar int32 value +SUBROUTINE fhash_tbl_get_int32_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT32), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, i32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int32_ptr + +!> Get wrapper to directly retrieve a scalar int64 value +SUBROUTINE fhash_tbl_get_int64_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + INTEGER(INT64), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, i64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_int64_ptr + +!> Get wrapper to directly retrieve a scalar float value +SUBROUTINE fhash_tbl_get_float_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(sp), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, r32=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_float_ptr + +!> Get wrapper to directly retrieve a scalar double value +SUBROUTINE fhash_tbl_get_double_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + REAL(dp), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, r64=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_double_ptr + +!> Get wrapper to directly retrieve a scalar character value +SUBROUTINE fhash_tbl_get_char_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CHARACTER(:), POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, char=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_char_ptr + +!> Get wrapper to directly retrieve a scalar logical value +SUBROUTINE fhash_tbl_get_logical_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + LOGICAL, POINTER, INTENT(out) :: VALUE !! Output value pointer + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, bool=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_logical_ptr + +!> Get wrapper to directly retrieve underlying polymorhpic scalar value +SUBROUTINE fhash_tbl_get_raw_ptr(tbl, key, VALUE, stat) + CLASS(fhash_tbl_t), INTENT(in) :: tbl !! Hash table object + CLASS(fhash_key_t), INTENT(in) :: key !! Key to retrieve + CLASS(*), POINTER, INTENT(out) :: VALUE !! Output value + INTEGER, INTENT(out), OPTIONAL :: stat !! Status flag. Zero if successful. + + CALL fhash_tbl_get_intrinsic_scalar_ptr(tbl, key, raw=VALUE, stat=stat) + +END SUBROUTINE fhash_tbl_get_raw_ptr + +END MODULE fhash_tbl diff --git a/src/modules/Fhash/src/fhash_tbl_iter.F90 b/src/modules/Fhash/src/fhash_tbl_iter.F90 new file mode 100644 index 000000000..45188529d --- /dev/null +++ b/src/modules/Fhash/src/fhash_tbl_iter.F90 @@ -0,0 +1,83 @@ +MODULE fhash_tbl_iter +USE fhash_tbl, ONLY: fhash_tbl_t +USE fhash_key_base, ONLY: fhash_key_t +USE fhash_data_container, ONLY: fhash_container_t +USE fhash_sll +IMPLICIT NONE + +PRIVATE +PUBLIC fhash_iter_t + +!> Iterator type for iterating over hash table items +TYPE fhash_iter_t + + TYPE(fhash_tbl_t), POINTER :: tbl => NULL() + + INTEGER :: bucket = 1 + INTEGER :: depth = 1 + +CONTAINS + PROCEDURE :: next => fhash_iter_next + PROCEDURE :: reset => fhash_iter_reset +END TYPE fhash_iter_t + +INTERFACE fhash_iter_t + MODULE PROCEDURE :: fhash_iter_init +END INTERFACE fhash_iter_t + +CONTAINS + +!> Initialise fhash iterator +FUNCTION fhash_iter_init(tbl) RESULT(iter) + TYPE(fhash_tbl_t), INTENT(in), TARGET :: tbl + TYPE(fhash_iter_t) :: iter + + iter%tbl => tbl + +END FUNCTION fhash_iter_init + +!> Return next item from iterator +FUNCTION fhash_iter_next(iter, key, DATA) RESULT(found) + CLASS(fhash_iter_t), INTENT(inout) :: iter + CLASS(fhash_key_t), INTENT(out), ALLOCATABLE :: key + CLASS(*), ALLOCATABLE, INTENT(out) :: DATA + LOGICAL :: found + + TYPE(fhash_container_t), POINTER :: data_container + CLASS(*), POINTER :: data_out + + found = .FALSE. + + IF (.NOT. ASSOCIATED(iter%tbl)) RETURN + + DO WHILE (.NOT. found) + IF (iter%bucket > SIZE(iter%tbl%buckets)) RETURN + IF (.NOT. ALLOCATED(iter%tbl%buckets(iter%bucket)%key)) THEN + iter%bucket = iter%bucket + 1 + CYCLE + END IF + call sll_get_at(iter%tbl%buckets(iter%bucket),iter%depth,key,data_container,found) + IF (iter%depth > node_depth(iter%tbl%buckets(iter%bucket))) THEN + iter%bucket = iter%bucket + 1 + iter%depth = 1 + ELSE + iter%depth = iter%depth + 1 + END IF + END DO + + IF (found) THEN + CALL data_container%get(raw=DATA) ! Extract underlying polymorphic data + END IF + +END FUNCTION fhash_iter_next + +!> Reset iterator to beginning +SUBROUTINE fhash_iter_reset(iter) + CLASS(fhash_iter_t), INTENT(inout) :: iter + + iter%bucket = 1 + iter%depth = 1 + +END SUBROUTINE fhash_iter_reset + +END MODULE fhash_tbl_iter diff --git a/src/modules/FiniteElement/src/FiniteElement_Class.F90 b/src/modules/FiniteElement/src/FiniteElement_Class.F90 index 84ace8b9d..d453184d3 100644 --- a/src/modules/FiniteElement/src/FiniteElement_Class.F90 +++ b/src/modules/FiniteElement/src/FiniteElement_Class.F90 @@ -46,6 +46,8 @@ MODULE FiniteElement_Class PROCEDURE, PUBLIC, PASS(obj) :: Initiate => fe_Initiate !! Constructor method for AbstractFE element !! This method can be overloaded by Subclass of this abstract class. + PROCEDURE, PUBLIC, PASS( obj ) :: InitiateLagrangeFE => & + & fe_InitiateLagrangeFE PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & fe_CheckEssentialParam END TYPE FiniteElement_ @@ -88,6 +90,50 @@ MODULE SUBROUTINE fe_Initiate(obj, param) END SUBROUTINE fe_Initiate END INTERFACE +!---------------------------------------------------------------------------- +! Initiate@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 27 Aug 2022 +! summary: Initiates an instance of the finite element + +INTERFACE + MODULE SUBROUTINE fe_InitiateLagrangeFE(obj, nsd, & + & elemType, baseContinuity, baseInterpolation, ipType, & + & basisType, alpha, beta, lambda, order) + CLASS(FiniteElement_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: nsd + !! Number of spatial dimension + INTEGER(I4B), INTENT(IN) :: elemType + !! Type of finite element + !! Line, Triangle, Quadrangle, Tetrahedron, Prism, Pyramid, + !! Hexahedron + CHARACTER(*), INTENT(IN) :: baseContinuity + !! Continuity or Conformity of basis function. + !! H1* (default), HDiv, HCurl, DG + CHARACTER(*), INTENT(IN) :: baseInterpolation + !! Basis function family used for interpolation. + !! LagrangeInterpolation, LagrangePolynomial + INTEGER(I4B), INTENT(IN) :: ipType + !! Interpolation point type, It is required when + !! baseInterpol is LagrangePolynomial. It can take following + !! values: + !! Legendre, Chebyshev, Ultraspherical, Equidistance, Jacobi + INTEGER(I4B), INTENT(IN) :: basisType + !! Basis type: + !! Legendre, Lobatto, Ultraspherical, Jacobi, Monomial + REAL(DFP), INTENT(IN) :: alpha + !! Jacobi parameter + REAL(DFP), INTENT(IN) :: beta + !! Jacobi parameter + REAL(DFP), INTENT(IN) :: lambda + !! Ultraspherical parameters + INTEGER(I4B), INTENT(IN) :: order + !! Isotropic Order of finite element + END SUBROUTINE fe_InitiateLagrangeFE +END INTERFACE + !---------------------------------------------------------------------------- ! Deallocate@Methods !---------------------------------------------------------------------------- @@ -150,9 +196,6 @@ MODULE SUBROUTINE SetFiniteElementParam( & !! Hexahedron CHARACTER(*), INTENT(IN) :: baseContinuity !! Continuity or Conformity of basis function. - !! This parameter is used to determine the nodal coordinates of - !! reference element, when xij is not present. - !! If xij is present then this parameter is ignored !! H1* (default), HDiv, HCurl, DG CHARACTER(*), INTENT(IN) :: baseInterpolation !! Basis function family used for interpolation. @@ -167,9 +210,13 @@ MODULE SUBROUTINE SetFiniteElementParam( & INTEGER(I4B), OPTIONAL, INTENT(IN) :: ipType !! Interpolation point type, It is required when !! baseInterpol is LagrangePolynomial + !! Legendre, Chebyshev, Ultraspherical, Equidistance + !! Jacobi INTEGER(I4B), OPTIONAL, INTENT(IN) :: basisType(:) - !! Basis type: Legendre, Lobatto, Ultraspherical, + !! Basis type: + !! Legendre, Lobatto, Ultraspherical, !! Jacobi, Monomial + !! Basis in x, y, and z direction. REAL(DFP), OPTIONAL, INTENT(IN) :: alpha(:) !! Jacobi parameter REAL(DFP), OPTIONAL, INTENT(IN) :: beta(:) @@ -198,10 +245,11 @@ END SUBROUTINE SetFiniteElementParam ! summary: Initiate vector of FiniteElement pointers INTERFACE Initiate - MODULE SUBROUTINE fe_Initiate1(obj, param, dom) + MODULE SUBROUTINE fe_Initiate1(obj, param, dom, dim) TYPE(FiniteElementPointer_), ALLOCATABLE, INTENT(INOUT) :: obj(:) TYPE(ParameterList_), INTENT(IN) :: param CLASS(Domain_), INTENT(IN) :: dom + INTEGER(I4B), INTENT(IN) :: dim END SUBROUTINE fe_Initiate1 END INTERFACE Initiate diff --git a/src/modules/Toml/CMakeLists.txt b/src/modules/Toml/CMakeLists.txt new file mode 100644 index 000000000..c3395ef97 --- /dev/null +++ b/src/modules/Toml/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/TomlUtility.F90 +) diff --git a/src/modules/Toml/src/TomlUtility.F90 b/src/modules/Toml/src/TomlUtility.F90 new file mode 100644 index 000000000..8fc0515d1 --- /dev/null +++ b/src/modules/Toml/src/TomlUtility.F90 @@ -0,0 +1,302 @@ +! 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 TomlUtility +USE GlobalData +USE tomlf, ONLY: toml_table +USE TxtFile_Class +USE ExceptionHandler_Class, ONLY: e +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "TomlUtility" +PUBLIC :: GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int8_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT8), ALLOCATABLE, INTENT(OUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int8_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int16_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT16), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int16_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int32_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT32), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int32_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int64_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT64), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int64_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue Integer Vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real32_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL32), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real32_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: GetValue integer vectors + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real64_r1(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL64), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real64_r1 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int8_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT8), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int8_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int16_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT16), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int16_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int32_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT32), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int32_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_int64_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + INTEGER(INT64), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_int64_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real32_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL32), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real32_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@Methods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get values for a matrix + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_real64_r2(table, key, VALUE, origin, stat, & + & isFound) + TYPE(toml_table), INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: key + REAL(REAL64), ALLOCATABLE, INTENT(OUT) :: VALUE(:, :) + INTEGER(I4B), OPTIONAL, INTENT(INout) :: origin + INTEGER(I4B), OPTIONAL, INTENT(INout) :: stat + LOGICAL(LGT), OPTIONAL, INTENT(INOUT) :: isFound + END SUBROUTINE toml_get_real64_r2 +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate table from toml file + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_from_file(table, afile) + TYPE(toml_table), ALLOCATABLE, INTENT(INOUT) :: table + TYPE(TxtFile_), INTENT(INOUT) :: afile + END SUBROUTINE toml_get_from_file +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! GetValue@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate table from toml file + +INTERFACE GetValue + MODULE SUBROUTINE toml_get_from_filename(table, filename) + TYPE(toml_table), ALLOCATABLE, INTENT(INOUT) :: table + CHARACTER(*), INTENT(IN) :: filename + END SUBROUTINE toml_get_from_filename +END INTERFACE GetValue + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE TomlUtility diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 index 4608ec207..352179b99 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 @@ -17,29 +17,10 @@ SUBMODULE(AbstractBC_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" -CALL e%raiseError(modName//'::'//myName//' - '// & - & 'This routine should be implemented by children of AbstractBC_') -END PROCEDURE bc_CheckEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_Initiate -CHARACTER(*), PARAMETER :: myName = "bc_Initiate" -CALL e%raiseError(modName//'::'//myName//' - '// & - & 'This routine should be implemented by children of AbstractBC_') -END PROCEDURE bc_Initiate - !---------------------------------------------------------------------------- ! Deallocate !---------------------------------------------------------------------------- @@ -65,165 +46,153 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractBCcheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "AbstractBCcheckEssentialParam" +MODULE PROCEDURE bc_checkessentialparam +CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" INTEGER(I4B) :: ii -INTEGER(I4B), PARAMETER :: maxEssentialParam = 7 -TYPE(String) :: essentialParam(maxEssentialParam) - -essentialParam(1) = prefix//"/name" -essentialParam(2) = prefix//"/idof" -essentialParam(3) = prefix//"/nodalValueType" -essentialParam(4) = prefix//"/useFunction" -essentialParam(5) = prefix//"/isNormal" -essentialParam(6) = prefix//"/isTangent" -essentialParam(7) = prefix//"/useExternal" - -DO ii = 1, maxEssentialParam - IF (.NOT. param%isPresent(key=TRIM(essentialParam(ii)%chars()))) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & TRIM(essentialParam(ii)%chars())//' should be present in param') - END IF -END DO +TYPE(String), ALLOCATABLE :: essentialParam(:) +TYPE(String) :: astr, prefix0 -END PROCEDURE AbstractBCcheckEssentialParam +IF (PRESENT(prefix)) THEN + prefix0 = prefix +ELSE + prefix0 = obj%GetPrefix() +END IF + +astr = "/name/idof/nodalValueType/useFunction/isNormal/isTangent/useExternal" + +CALL astr%Split(essentialParam, sep="/") +CALL CheckEssentialParam(obj=param, & + & keys=essentialParam, & + & prefix=prefix0%chars(), & + & myName=myName, & + & modName=modName) +!NOTE: CheckEssentialParam param is defined in easifemClasses FPL_Method + +IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" + END DO + DEALLOCATE (essentialParam) +END IF +astr = "" +prefix0 = "" +END PROCEDURE bc_CheckEssentialParam !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE setAbstractBCParam -INTEGER(I4B) :: ierr -CHARACTER(*), PARAMETER :: myName = "setAbstractBCParam" +MODULE PROCEDURE SetAbstractBCParam +CHARACTER(*), PARAMETER :: myName = "SetAbstractBCParam()" -IF (PRESENT(name)) THEN - ierr = param%set(key=TRIM(prefix)//"/name", VALUE=TRIM(name)) -ELSE - ierr = param%set(key=TRIM(prefix)//"/name", VALUE="AbstractBC") -END IF +CALL Set(param, datatype="char", prefix=prefix, key="name", & + & VALUE=input(option=name, default=default_name)) -IF (PRESENT(idof)) THEN - ierr = param%set(key=TRIM(prefix)//"/idof", VALUE=idof) -ELSE - ierr = param%set(key=TRIM(prefix)//"/idof", VALUE=0_I4B) -END IF +CALL Set(param, datatype=0_I4B, prefix=prefix, key="idof", & + & VALUE=input(option=idof, default=default_idof)) -IF (PRESENT(nodalValueType)) THEN - ierr = param%set(key=TRIM(prefix)//"/nodalValueType", VALUE=nodalValueType) -ELSE - ierr = param%set(key=TRIM(prefix)//"/nodalValueType", VALUE=-1_I4B) -END IF +CALL Set(param, datatype=0_I4B, prefix=prefix, key="nodalValueType", & + & VALUE=input(option=nodalValueType, default=default_nodalValueType)) -IF (PRESENT(useFunction)) THEN - ierr = param%set(key=TRIM(prefix)//"/useFunction", VALUE=useFunction) -ELSE - ierr = param%set(key=TRIM(prefix)//"/useFunction", VALUE=.FALSE.) -END IF +CALL Set(param, datatype=.TRUE., prefix=prefix, key="useFunction", & + & VALUE=input(option=useFunction, default=default_useFunction)) -IF (PRESENT(isNormal)) THEN - ierr = param%set(key=TRIM(prefix)//"/isNormal", VALUE=isNormal) - IF (PRESENT(idof)) THEN - IF (idof .GT. 0 .AND. isNormal) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'When isNormal is true, idof cannot be greater than 0') - END IF - END IF -ELSE - ierr = param%set(key=TRIM(prefix)//"/isNormal", VALUE=.FALSE.) -END IF +CALL Set(param, datatype=.TRUE., prefix=prefix, key="isNormal", & + & VALUE=input(option=isNormal, default=default_isNormal)) + +CALL Set(param, datatype=.TRUE., prefix=prefix, key="isTangent", & + & VALUE=input(option=isTangent, default=default_isTangent)) -IF (PRESENT(isTangent)) THEN - ierr = param%set(key=TRIM(prefix)//"/isTangent", VALUE=isTangent) - IF (PRESENT(idof)) THEN - IF (idof .GT. 0 .AND. isTangent) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'When isTangent is true, idof cannot be greater than 0') - END IF +CALL Set(param, datatype=.TRUE., prefix=prefix, key="useExternal", & + & VALUE=input(option=useExternal, default=default_useExternal)) + +IF (PRESENT(isNormal) .AND. PRESENT(idof)) THEN + IF (idof .GT. 0 .AND. isNormal) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When isNormal is true, '// & + & 'idof CANNOT be greater than 0.') END IF -ELSE - ierr = param%set(key=TRIM(prefix)//"/isTangent", VALUE=.FALSE.) END IF -IF (PRESENT(useExternal)) THEN - ierr = param%set(key=TRIM(prefix)//"/useExternal", VALUE=useExternal) -ELSE - ierr = param%set(key=TRIM(prefix)//"/useExternal", VALUE=.FALSE.) +IF (PRESENT(isTangent) .AND. PRESENT(idof)) THEN + IF (idof .GT. 0 .AND. isTangent) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When isTangent is true, '// & + & 'idof cannot be greater than 0.') + END IF END IF -END PROCEDURE setAbstractBCParam +END PROCEDURE SetAbstractBCParam !---------------------------------------------------------------------------- -! AbstractBCInitiate +! Initiate !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractBCInitiate -CHARACTER(*), PARAMETER :: myName = "AbstractBCInitiate" -CHARACTER(:), ALLOCATABLE :: char_var -INTEGER(I4B) :: ierr +MODULE PROCEDURE bc_Initiate +CHARACTER(*), PARAMETER :: myName = "bc_Initiate()" +LOGICAL(LGT) :: isSelectionByMeshID, abool +TYPE(String) :: prefix -IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'AbstractBC_ object is already initiated') -END IF +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +prefix = obj%GetPrefix() +CALL obj%DEALLOCATE() -CALL obj%checkEssentialParam(param=param) +CALL obj%CheckEssentialParam(param=param, prefix=prefix%chars()) obj%isInitiated = .TRUE. obj%boundary = boundary obj%dom => dom -! + ! name -! -ALLOCATE (CHARACTER(param%DataSizeInBytes( & - & key=TRIM(prefix)//"/name")) :: char_var) -ierr = param%get(key=TRIM(prefix)//"/name", VALUE=char_var) -obj%name = char_var -DEALLOCATE (char_var) -! +CALL GetValue(obj=param, prefix=prefix%chars(), key="name", VALUE=obj%name) + ! idof -! -ierr = param%get(key=TRIM(prefix)//"/idof", VALUE=obj%idof) -! +CALL GetValue(obj=param, prefix=prefix%chars(), key="idof", VALUE=obj%idof) + ! nodalValueType -! -ierr = param%get(key=TRIM(prefix)//"/nodalValueType", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="nodalValueType", & & VALUE=obj%nodalValueType) -! + ! useFunction -! -ierr = param%get(key=TRIM(prefix)//"/useFunction", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="useFunction", & & VALUE=obj%useFunction) -! + ! isNormal -! -ierr = param%get(key=TRIM(prefix)//"/isNormal", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="isNormal", & & VALUE=obj%isNormal) -! + ! isTangent -! -ierr = param%get(key=TRIM(prefix)//"/isTangent", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="isTangent", & & VALUE=obj%isTangent) -! + ! useExternal -! -ierr = param%get(key=TRIM(prefix)//"/useExternal", & +CALL GetValue(obj=param, prefix=prefix%chars(), key="useExternal", & & VALUE=obj%useExternal) -! + ! check -! -IF (boundary%isSelectionByMeshID & - & .AND. (.NOT. obj%useFunction) & - & .AND. (.NOT. obj%useExternal)) THEN - IF (obj%nodalValueType .NE. Constant) THEN - CALL e%raiseWarning(modName//'::'//myName//" - "// & - & "When meshSelection is by MeshID & - & and `useFunction` is false, then & - & `nodalValueType` in `AbstractBC_` & - & object should be Constant.") - END IF +CALL boundary%GetParam(isSelectionByMeshID=isSelectionByMeshID) +abool = boundary%isSelectionByMeshID & + & .AND. (.NOT. obj%useFunction) & + & .AND. (.NOT. obj%useExternal) & + & .AND. (obj%nodalValueType .NE. Constant) + +IF (abool) THEN + CALL e%RaiseWarning(modName//'::'//myName//" - "// & + & "When meshSelection is by MeshID"//CHAR_LF// & + & " and `useFunction` is false, then"//CHAR_LF// & + & " `nodalValueType` in `AbstractBC_`"//CHAR_LF// & + & " object should be Constant.") END IF -END PROCEDURE AbstractBCInitiate +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractBCInitiate()') +#endif +END PROCEDURE bc_Initiate !---------------------------------------------------------------------------- ! diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 index 017a1f00a..2ae68fc55 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 @@ -142,6 +142,24 @@ END PROCEDURE bc_Get +!---------------------------------------------------------------------------- +! bc_GetFEVar +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetFEVar +CHARACTER(*), PARAMETER :: myName = "bc_GetFEVar()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine is under development.') + +! If useFunction is true then +! if constant +! if time +! if space +! if space-time + +! If useFunction is not true then +END PROCEDURE bc_GetFEVar + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -265,7 +283,16 @@ IF (PRESENT(nodalValueType)) nodalValueType = obj%nodalValueType IF (PRESENT(isInitiated)) isInitiated = obj%isInitiated IF (PRESENT(useExternal)) useExternal = obj%useExternal - END PROCEDURE bc_GetQuery +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetPrefix +CHARACTER(*), PARAMETER :: myName = "bc_GetPrefix()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child class.') +END PROCEDURE bc_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 index cf381f35f..12f6c0d24 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 @@ -17,43 +17,49 @@ SUBMODULE(AbstractBC_Class) IOMethods USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! +! Import !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Import CHARACTER(*), PARAMETER :: myName = "bc_Import" TYPE(String) :: dsetname, strval -INTEGER(I4B) :: ierr REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The object is already initiated, deallocate first!') END IF obj%isInitiated = .TRUE. obj%dom => dom -CALL e%raiseInformation(modName//"::"//myName//" - "// & +CALL e%RaiseInformation(modName//"::"//myName//" - "// & & "Importing Boundary condition") IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF IF (.NOT. hdf5%isRead()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have read permission') END IF dsetname = TRIM(group)//"/name" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset name should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -62,7 +68,7 @@ dsetname = TRIM(group)//"/idof" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset idof should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -71,7 +77,7 @@ dsetname = TRIM(group)//"/nodalValueType" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset nodalValueType should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -90,7 +96,7 @@ dsetname = TRIM(group)//"/useFunction" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset useFunction should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -99,7 +105,7 @@ dsetname = TRIM(group)//"/useExternal" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset useExternal should be present') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), & @@ -108,7 +114,7 @@ dsetname = TRIM(group)//"/Boundary" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset Boundary, which is a group, should be present') ELSE CALL obj%boundary%IMPORT(hdf5=hdf5, group=dsetname%chars()) @@ -117,7 +123,7 @@ IF (.NOT. obj%UseFunction) THEN dsetname = TRIM(group)//"/NodalValue" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset NodalValue should be present') END IF SELECT CASE (obj%nodalValueType) @@ -143,31 +149,30 @@ END PROCEDURE bc_Import !---------------------------------------------------------------------------- -! +! Export !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Export CHARACTER(*), PARAMETER :: myName = "bc_Export" TYPE(String) :: dsetname, strval -INTEGER(I4B) :: ierr REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) IF (.NOT. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The object is not initiated, initiate it first!') END IF -CALL e%raiseInformation(modName//"::"//myName//" - "// & +CALL e%RaiseInformation(modName//"::"//myName//" - "// & & "Exporting Dirichlet Boundary Condition") IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF IF (.NOT. hdf5%isWrite()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have write permission') END IF @@ -214,7 +219,7 @@ IF (.NOT. obj%UseFunction) THEN dsetname = TRIM(group)//"/NodalValue" IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'NodalValue is not allocated, it seems NodalValue is not set') END IF SELECT CASE (obj%nodalValueType) @@ -238,7 +243,7 @@ END PROCEDURE bc_Export !---------------------------------------------------------------------------- -! +! Display !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Display @@ -267,24 +272,24 @@ END SELECT CALL Display("# nodalValueType : "//TRIM(strval%chars()), unitNo=unitNo) -CALL Display(obj%useFunction, "# useFunction : ", unitNo=unitNo) -CALL Display(obj%useExternal, "# useExternal : ", unitNo=unitNo) +CALL Display(obj%useFunction, "useFunction : ", unitNo=unitNo) +CALL Display(obj%useExternal, "useExternal : ", unitNo=unitNo) CALL obj%Boundary%Display(msg="Boundary : ", unitNo=unitNo) IF (.NOT. obj%UseFunction) THEN IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL Display("# NodalValue : NOT ALLOCATED", unitNo=unitNo) + CALL Display("NodalValue : NOT ALLOCATED", unitNo=unitNo) ELSE SELECT CASE (obj%nodalValueType) CASE (Constant) real0 = obj%NodalValue(1, 1) - CALL Display(real0, "# NodalValue : ", unitNo=unitNo) + CALL Display(real0, "NodalValue : ", unitNo=unitNo) CASE (Space, Time) real1 = obj%NodalValue(:, 1) - CALL Display(real1, "# NodalValue : ", unitNo=unitNo, orient="col") + CALL Display(real1, "NodalValue : ", unitNo=unitNo, orient="col") CASE (SpaceTime) real2 = obj%NodalValue(:, :) - CALL Display(real2, "# NodalValue : ", unitNo=unitNo) + CALL Display(real2, "NodalValue : ", unitNo=unitNo) END SELECT END IF END IF @@ -293,6 +298,229 @@ IF (ALLOCATED(real2)) DEALLOCATE (real2) END PROCEDURE bc_Display +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportParamFromToml +CHARACTER(*), PARAMETER :: myName = "bc_ImportParamFromToml()" +INTEGER(I4B) :: origin, stat, nodalValueType, idof +LOGICAL(LGT) :: useFunction, isNormal, isTangent, useExternal +TYPE(String) :: nodalValueType_string, name, astr + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportParamFromToml()') +#endif + +CALL toml_get(table, "useFunction", useFunction, & + & default_useFunction, origin=origin, stat=stat) + +CALL toml_get(table, "isTangent", isTangent, & + & default_isTangent, origin=origin, stat=stat) + +CALL toml_get(table, "isNormal", isNormal, & + & default_isNormal, origin=origin, stat=stat) + +CALL toml_get(table, "useExternal", useExternal, & + & default_useExternal, origin=origin, stat=stat) + +CALL toml_get(table, "nodalValueType", nodalValueType_string%raw, & + & default_nodalValueType_char, origin=origin, stat=stat) + +CALL toml_get(table, "idof", idof, default_idof, origin=origin, stat=stat) + +CALL toml_get(table, "name", name%raw, & + & obj%GetPrefix(), origin=origin, stat=stat) + +astr = nodalValueType_string%Upper() +SELECT CASE (astr%chars()) +CASE ("CONSTANT") + nodalValueType = Constant +CASE ("TIME") + nodalValueType = Time +CASE ("SPACE") + nodalValueType = Space +CASE ("SPACETIME") + nodalValueType = SpaceTime +CASE DEFAULT + nodalValueType = default_nodalValueType +END SELECT +astr = "" + +CALL SetAbstractBCParam( & + & param=param, & + & prefix=obj%GetPrefix(), & + & name=name%chars(), & + & idof=idof, & + & nodalValueType=nodalValueType, & + & useFunction=useFunction, & + & isNormal=isNormal, & + & isTangent=isTangent, & + & useExternal=useExternal & + & ) + +name = "" +nodalValueType_string = "" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "meshSelect_ImportFromToml1()" +TYPE(ParameterList_) :: param +TYPE(toml_table), POINTER :: node +TYPE(MeshSelection_) :: boundary +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: bool1, isFound +REAL(DFP), ALLOCATABLE :: value_r1(:), value_r2(:, :) +REAL(DFP) :: constantValue + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif +CALL param%Initiate() + +CALL obj%ImportParamFromToml(param=param, table=table) + +node => NULL() +CALL toml_get(table, "boundary", node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find [boundary] table in config.') +END IF + +CALL boundary%ImportFromToml(table=node, dom=dom) +CALL obj%Initiate(param=param, boundary=boundary, dom=dom) + +IF (obj%useFunction) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: useFunction = .TRUE., currently you cannot '// & + & 'specify the function.') + RETURN +END IF + +SELECT CASE (obj%nodalValueType) +CASE (Constant) + CALL toml_get(table, "value", constantValue, origin=origin, stat=stat) + IF (stat .NE. toml_stat%success) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: nodalValueType is Constant. So, '// & + & 'value should be a constant (scalar real value).') + RETURN + END IF + CALL obj%Set(constantNodalValue=constantValue) + +CASE (Space, Time) + CALL GetValue(table=table, key="value", VALUE=value_r1, & + & isFound=isFound, origin=origin, stat=stat) + + bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) + + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & + & 'value should be a vector of real numbers.'//CHAR_LF// & + & 'You can specify a vector by directly giving the vector values.'// & + & 'Otherwise, specify filename which contains the vector'// & + & 'values.') + RETURN + END IF + + IF (obj%nodalValueType .EQ. Space) THEN + CALL obj%Set(spaceNodalValue=value_r1) + ELSE + CALL obj%Set(timeNodalValue=value_r1) + END IF + +CASE (SpaceTime) + CALL GetValue(table=table, key="value", VALUE=value_r2, & + & isFound=isFound, origin=origin, stat=stat) + + bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) + + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & + & 'value should be a vector of real numbers.'//CHAR_LF// & + & 'You can specify a vector by directly giving the vector values.'// & + & 'Otherwise, specify filename which contains the vector'// & + & 'values.') + RETURN + END IF + + CALL obj%Set(spaceTimeNodalValue=value_r2) + +END SELECT + +CALL param%DEALLOCATE() +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml()') +#endif +END PROCEDURE bc_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +INTEGER(I4B) :: origin, stat + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +node => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find ['//tomlName//"] table in config.") +END IF + +CALL obj%ImportFromToml(table=node, dom=dom) + +#ifdef DEBUG_VER +IF (PRESENT(printToml)) THEN + CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & + & unitNo=stdout) +END IF +#endif + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml2 + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 index a1cbf4aa5..1890a40b1 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 @@ -26,172 +26,156 @@ MODULE PROCEDURE bc_set CHARACTER(*), PARAMETER :: myName = "bc_set" +LOGICAL(LGT) :: notFunc_notExt, isTimeFunc, isSpaceFunc, isSTFunc, isFunc, & + & isConstVal, isSpaceVal, isSTVal, isTimeVal, bool1, bool2 IF (.NOT. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'AbstractBC_ object is not initiated, initiate it first.') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR ] :: AbstractBC_ object is not initiated.') END IF -IF (.NOT. obj%UseFunction .AND. .NOT. obj%useExternal) THEN - - IF (PRESENT(TimeFunction) .OR. PRESENT(SpaceFunction) & - & .OR. PRESENT(SpaceTimeFunction)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is initiated with useFunction=.FALSE."//CHAR_LF// & - & " and useExternal=.FALSE."//CHAR_LF// & - & "So you cannot provide TimeFunction, SpaceFunction, SpaceTimeFunction") - END IF - - ! constant - - IF (PRESENT(ConstantNodalValue)) THEN - - IF (obj%nodalValueType .NE. Constant) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Constant"// & - & CHAR_LF// & - & 'So, ConstantNodalValue cannot be present') - - ELSE - - CALL Reallocate(obj%NodalValue, 1, 1) - obj%NodalValue = ConstantNodalValue - RETURN - - END IF - - END IF - - ! SpaceNodalValue - - IF (PRESENT(SpaceNodalValue)) THEN - - IF (obj%nodalValueType .NE. Space) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Space"// & - & CHAR_LF// & - & 'So, SpaceNodalValue cannot be present') - - ELSE - - CALL Reallocate(obj%NodalValue, SIZE(SpaceNodalValue), 1) - obj%NodalValue(:, 1) = SpaceNodalValue - RETURN - - END IF - - END IF - - ! TimeNodalValue - - IF (PRESENT(TimeNodalValue)) THEN - - IF (obj%nodalValueType .NE. Time) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Time"// & - & CHAR_LF// & - & 'So, TimeNodalValue cannot be present') - - ELSE - - CALL Reallocate(obj%NodalValue, SIZE(TimeNodalValue), 1) - obj%NodalValue(:, 1) = TimeNodalValue - RETURN - - END IF - - END IF - - ! SpaceTimeNodalValue - - IF (PRESENT(SpaceTimeNodalValue)) THEN - - IF (obj%nodalValueType .NE. SpaceTime) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, SpaceTimeNodalValue cannot be present') - - ELSE - - obj%NodalValue = SpaceTimeNodalValue - RETURN - - END IF - - END IF - -ELSE - - ! SpaceFunction - - IF (PRESENT(SpaceFunction)) THEN - - IF (obj%nodalValueType .NE. Space) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Space"// & - & CHAR_LF// & - & 'So, SpaceFunction cannot be present') - - ELSE - - obj%SpaceFunction => SpaceFunction - RETURN - - END IF - - END IF - - ! TimeNodalValue - - IF (PRESENT(TimeFunction)) THEN - - IF (obj%nodalValueType .NE. Time) THEN - - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=Time"// & - & CHAR_LF// & - & 'So, TimeFunction cannot be present') +notFunc_notExt = (.NOT. obj%useFunction) .AND. & +& (.NOT. obj%useExternal) + +isTimeFunc = PRESENT(timeFunction) +isSpaceFunc = PRESENT(spaceFunction) +isSTFunc = PRESENT(spaceTimeFunction) +isFunc = isSpaceFunc .OR. isTimeFunc .OR. isSTFunc +isConstVal = PRESENT(constantNodalValue) +isSpaceVal = PRESENT(spaceNodalValue) +isTimeVal = PRESENT(timeNodalValue) +isSTVal = PRESENT(spaceTimeNodalValue) + +IF (notFunc_notExt .AND. isFunc) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "//CHAR_LF// & + & "with useFunction=.FALSE. and useExternal=.FALSE."//CHAR_LF// & + & "So you cannot provide timeFunction, spaceFunction, spaceTimeFunction") +END IF - ELSE +bool1 = notFunc_notExt .AND. isConstVal +bool2 = bool1 .AND. obj%nodalValueType .NE. Constant +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Constant "//CHAR_LF// & + & 'So, constantNodalValue cannot be present') + RETURN +END IF - obj%TimeFunction => TimeFunction - RETURN +! constant +IF (bool1) THEN + CALL Reallocate(obj%NodalValue, 1, 1) + obj%NodalValue = constantNodalValue + RETURN +END IF - END IF +! spaceNodalValue +bool1 = notFunc_notExt .AND. isSpaceVal +bool2 = bool1 .AND. (obj%nodalValueType .NE. Space) +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Space"//CHAR_LF// & + & 'So, spaceNodalValue cannot be present.') + RETURN +END IF - END IF +IF (bool1) THEN + CALL Reallocate(obj%NodalValue, SIZE(spaceNodalValue), 1) + obj%NodalValue(:, 1) = spaceNodalValue + RETURN +END IF - ! SpaceTimeNodalValue +! timeNodalValue +bool1 = notFunc_notExt .AND. isTimeVal +bool2 = bool1 .AND. (obj%nodalValueType .NE. Time) +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Time"//CHAR_LF// & + & 'So, timeNodalValue cannot be present.') + RETURN +END IF - IF (PRESENT(SpaceTimeFunction)) THEN +IF (bool1) THEN + CALL Reallocate(obj%NodalValue, SIZE(timeNodalValue), 1) + obj%NodalValue(:, 1) = timeNodalValue + RETURN +END IF - IF (obj%nodalValueType .NE. SpaceTime) THEN +! spaceTimeNodalValue +bool1 = notFunc_notExt .AND. isSTVal +bool2 = bool1 .AND. (obj%nodalValueType .NE. SpaceTime) +IF (bool2) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & + & " nodalValueType=SpaceTime"// & + & CHAR_LF// & + & 'So, spaceTimeNodalValue cannot be present') + RETURN +END IF +IF (bool1) THEN + obj%NodalValue = spaceTimeNodalValue + RETURN +END IF - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is not initiated with nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, SpaceTimeFunction cannot be present') +! spaceFunction +bool1 = isSpaceFunc .AND. (obj%nodalValueType .NE. Space) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & + & "with nodalValueType=Space"// & + & CHAR_LF// & + & 'So, spaceFunction cannot be present') + RETURN +END IF - ELSE +IF (isSpaceFunc) THEN + obj%spaceFunction => spaceFunction + RETURN +END IF - obj%SpaceTimeFunction => SpaceTimeFunction - RETURN +! timeFunction +bool1 = isTimeFunc .AND. (obj%nodalValueType .NE. Time) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & + & "nodalValueType=Time"// & + & CHAR_LF// & + & 'So, timeFunction cannot be present') + RETURN +END IF - END IF +IF (isTimeFunc) THEN + obj%timeFunction => timeFunction + RETURN +END IF - END IF +! spaceTimeFunction +bool1 = isSTFunc .AND. (obj%nodalValueType .NE. SpaceTime) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & + & "nodalValueType=SpaceTime"// & + & CHAR_LF// & + & 'So, spaceTimeFunction cannot be present') + RETURN +END IF - CALL e%raiseError(modName//'::'//myName//" - "// & - & "AbstractBC_::obj is initiated with useFunction=TRUE"// & - & CHAR_LF// & - & 'So, SpaceFunction, TimeFunction, or SpaceTimeFunction should be present') +IF (isSTFunc) THEN + obj%spaceTimeFunction => spaceTimeFunction + RETURN +END IF +IF (obj%useFunction .AND. (.NOT. isFunc)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "// & + & "with useFunction=TRUE"// & + & CHAR_LF// & + & 'So, spaceFunction, timeFunction, or spaceTimeFunction '// & + & 'should be present') + RETURN END IF END PROCEDURE bc_set diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 index b37d055f4..8ba7af4f3 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@ConstructorMethods.F90 @@ -19,45 +19,6 @@ IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_checkEssentialParam -CALL AbstractBCcheckEssentialParam(& - & obj=obj, & - & param=param, & - & prefix=myprefix) -END PROCEDURE bc_checkEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE SetDirichletBCParam -CALL SetAbstractBCParam(& - & param=param, & - & prefix=myprefix, & - & name=name, & - & idof=idof, & - & nodalValueType=nodalValueType, & - & useFunction=input(option=useFunction, default=.FALSE.), & - & isNormal=input(option=isNormal, default=.FALSE.), & - & isTangent=input(option=isTangent, default=.FALSE.)) -END PROCEDURE SetDirichletBCParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_Initiate -CALL AbstractBCInitiate(obj=obj, & -& param=param, & -& prefix=myprefix, & -& boundary=boundary, & -& dom=dom) -END PROCEDURE bc_Initiate - !---------------------------------------------------------------------------- ! Final !---------------------------------------------------------------------------- @@ -104,6 +65,11 @@ MODULE PROCEDURE bc_AddDirichletBC CHARACTER(*), PARAMETER :: myName = "bc_AddDirichletBC" +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AddDirichletBC()') +#endif + IF (dbcNo .GT. SIZE(dbc)) THEN CALL e%raiseError(modName//'::'//myName//" - "// & & '[OUT OF BOUND ERROR] :: dbcNo [= '//TOSTRING(dbcNo)// & @@ -124,6 +90,10 @@ & boundary=boundary, & & dom=dom) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AddDirichletBC()') +#endif END PROCEDURE bc_AddDirichletBC END SUBMODULE ConstructorMethods diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 index a5e2676b3..cbb5196f6 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@GetMethods.F90 @@ -42,4 +42,12 @@ END PROCEDURE bc_GetDirichletBCPointer +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetPrefix + ans = myprefix +END PROCEDURE bc_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 b/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 index 19e6ac5e2..68c12fa03 100644 --- a/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 +++ b/src/submodules/DirichletBC/src/DirichletBC_Class@IOMethods.F90 @@ -16,6 +16,105 @@ ! SUBMODULE(DirichletBC_Class) IOMethods +USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml1()" +TYPE(toml_table), POINTER :: node +TYPE(toml_array), POINTER :: array +INTEGER(I4B) :: origin, stat, tsize, ii, tsize1 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +tsize1 = SIZE(obj) + +array => NULL() +CALL toml_get(table, tomlName, array, origin=origin, & + & requested=.FALSE., stat=stat) + +IF (.NOT. ASSOCIATED(array)) THEN + IF (tsize1 .GT. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + ELSE + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + END IF + RETURN +END IF + +tsize = toml_len(array) +IF (tsize .NE. tsize1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The number of boundary condition '// char_lf// & + & ' in the toml config ('//tostring(tsize)//') is not same '// & + & ' as the size of obj ('//tostring(tsize1)//")") + RETURN +END IF + +DO ii = 1, tsize + node => NULL() + CALL toml_get(array, ii, node) + IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: DirichletBC '//tostring(ii)// & + & ' cannot be read from the toml file.') + END IF + IF (.NOT. ASSOCIATED(obj(ii)%ptr)) ALLOCATE (obj(ii)%ptr) + CALL obj(ii)%ptr%ImportFromToml(table=node, dom=dom) +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +CALL DirichletBCImportFromToml(obj=obj, table=table, dom=dom, & + & tomlName=tomlName) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml2 END SUBMODULE IOMethods diff --git a/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 b/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 index b5f9e9de3..b91075abf 100644 --- a/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 +++ b/src/submodules/FiniteElement/src/FiniteElement_Class@Methods.F90 @@ -20,7 +20,7 @@ CONTAINS !---------------------------------------------------------------------------- -! Initiate +! Initiate !---------------------------------------------------------------------------- MODULE PROCEDURE fe_Initiate @@ -28,7 +28,7 @@ END PROCEDURE fe_Initiate !---------------------------------------------------------------------------- -! CheckEssentialParam +! CheckEssentialParam !---------------------------------------------------------------------------- MODULE PROCEDURE fe_CheckEssentialParam @@ -41,22 +41,22 @@ MODULE PROCEDURE SetFiniteElementParam CALL SetAbstractFEParam( & -& param=param, & -& prefix=myprefix, & -& nsd=nsd, & -& elemType=elemType, & -& baseContinuity=baseContinuity, & -& baseInterpolation=baseInterpolation, & -& ipType=ipType, & -& basisType=basisType, & -& alpha=alpha, & -& beta=beta, & -& lambda=lambda, & -& order=order, & -& anisoOrder=anisoOrder, & -& edgeOrder=edgeOrder, & -& faceOrder=faceOrder, & -& cellOrder=cellOrder) + & param=param, & + & prefix=myprefix, & + & nsd=nsd, & + & elemType=elemType, & + & baseContinuity=baseContinuity, & + & baseInterpolation=baseInterpolation, & + & ipType=ipType, & + & basisType=basisType, & + & alpha=alpha, & + & beta=beta, & + & lambda=lambda, & + & order=order, & + & anisoOrder=anisoOrder, & + & edgeOrder=edgeOrder, & + & faceOrder=faceOrder, & + & cellOrder=cellOrder) END PROCEDURE SetFiniteElementParam !---------------------------------------------------------------------------- @@ -97,32 +97,73 @@ MODULE PROCEDURE fe_Initiate1 CHARACTER(*), PARAMETER :: myName = "fe_Initiate1()" TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr, ii, tElemType -INTEGER(I4B), ALLOCATABLE :: elemType(:) +INTEGER(I4B) :: ierr, ii, tsize +INTEGER(I4B), ALLOCATABLE :: elemType(:), order(:) sublist => NULL() -IF (.NOT. param%isSubList(key=myPrefix)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[ARGUMENT ERROR] :: '//myprefix//' should be a sublist') -END IF +IF (.NOT. param%isSubList(key=myPrefix)) RETURN ierr = param%GetSubList(key=myprefix, sublist=sublist) -elemType = dom%GetElemType(dim=-1_I4B) -tElemType = SIZE(elemType) +IF (ierr .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured while getting'// & + & ' the sublist from param.') +END IF + +elemType = dom%GetElemType(dim=dim) +order = dom%GetOrder(dim=dim) +tsize = SIZE(elemType) CALL DEALLOCATE (obj) -ALLOCATE(obj(tElemType) ) +ALLOCATE (obj(tsize)) -DO ii = 1, SIZE(elemType) +DO ii = 1, tsize ierr = sublist%Set(key=myprefix//"/elemType", VALUE=elemType(ii)) - ALLOCATE(FiniteElement_::obj(ii)%ptr) + ierr = sublist%Set(key=myprefix//"/order", VALUE=order(ii)) + ALLOCATE (FiniteElement_ :: obj(ii)%ptr) CALL obj(ii)%ptr%Initiate(param=param) END DO sublist => NULL() IF (ALLOCATED(elemType)) DEALLOCATE (elemType) +IF (ALLOCATED(order)) DEALLOCATE (order) END PROCEDURE fe_Initiate1 +!---------------------------------------------------------------------------- +! InitiateLagrangeFE +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fe_InitiateLagrangeFE +TYPE(ParameterList_) :: param +CHARACTER(*), PARAMETER :: myName="fe_InitiateLagrangeFE()" + +IF (baseInterpolation .NE. "LagrangePolynomial" & + & .OR. baseInterpolation .NE. "LagrangeInterpolation") THEN + CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[ARG ERROR] :: This routine is valid for baseInterpolation = ' // & + & 'LagrangePolynomial or LagrangeInterpolation ' // & + & ' given value of baseInterpolation is ' // trim(baseInterpolation)) +END IF + +CALL param%Initiate() +CALL SetFiniteElementParam( & + & param=param, & + & nsd=nsd, & + & elemType=elemType, & + & baseContinuity=baseContinuity, & + & baseInterpolation=baseInterpolation, & + & ipType=ipType, & + & basisType=[basisType], & + & alpha=[alpha], & + & beta=[beta], & + & lambda=[lambda], & + & order=order) + +CALL obj%Initiate(param) + +CALL param%DEALLOCATE() +END PROCEDURE fe_InitiateLagrangeFE + END SUBMODULE Methods diff --git a/src/submodules/Toml/CMakeLists.txt b/src/submodules/Toml/CMakeLists.txt new file mode 100644 index 000000000..7917e32bf --- /dev/null +++ b/src/submodules/Toml/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/TomlUtility@GetMethods.F90 +) diff --git a/src/submodules/Toml/src/TomlUtility@GetMethods.F90 b/src/submodules/Toml/src/TomlUtility@GetMethods.F90 new file mode 100644 index 000000000..6a6ebcd87 --- /dev/null +++ b/src/submodules/Toml/src/TomlUtility@GetMethods.F90 @@ -0,0 +1,199 @@ +! 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(TomlUtility) GetMethods +USE String_Class +USE TxtFile_Class +USE BaseMethod +USE tomlf, ONLY: & + & toml_error, & + & toml_load, & + & toml_parser_config, & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_context, & + & toml_terminal, & + & toml_load, & + & toml_array, & + & toml_stat +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int8_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int8_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int16_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int16_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int32_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int32_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int64_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_int64_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real32_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_real32_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real64_r1 +#include "./include/ReadVector.inc" +END PROCEDURE toml_get_real64_r1 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int8_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int8_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int16_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int16_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int32_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int32_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_int64_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_int64_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real32_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_real32_r2 + +!---------------------------------------------------------------------------- +! Get +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_real64_r2 +#include "./include/ReadMatrix.inc" +END PROCEDURE toml_get_real64_r2 + +!---------------------------------------------------------------------------- +! toml_get_from_file +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_from_file +CHARACTER(*), PARAMETER :: myName = "toml_get_from_file()" +LOGICAL(LGT) :: isNotOpen, isNotRead +LOGICAL(LGT), PARAMETER :: color = .TRUE. +INTEGER(I4B), PARAMETER :: detail = 1 +TYPE(toml_error), ALLOCATABLE :: error +TYPE(toml_context) :: context +TYPE(toml_terminal) :: terminal + +terminal = toml_terminal(color) +isNotOpen = .NOT. afile%IsOpen() +isNotRead = .NOT. afile%IsRead() + +IF (isNotRead .OR. isNotOpen) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The file is not open or does not have '// & + & 'the access to read!') +END IF + +CALL toml_load(table, & + & afile%GetUnitNo(), & + & context=context, & + & config=toml_parser_config(color=terminal, context_detail=detail), & + & error=error & + & ) + +IF (ALLOCATED(error)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & + & ' with following message: '//CHAR_LF//error%message) +END IF + +END PROCEDURE toml_get_from_file + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE toml_get_from_filename +CHARACTER(*), PARAMETER :: myName = "toml_get_from_filename()" +LOGICAL(LGT), PARAMETER :: color = .TRUE. +INTEGER(I4B), PARAMETER :: detail = 1 +TYPE(toml_error), ALLOCATABLE :: error +TYPE(toml_context) :: context +TYPE(toml_terminal) :: terminal + +terminal = toml_terminal(color) +CALL toml_load(table, & + & filename, & + & context=context, & + & config=toml_parser_config(color=terminal, context_detail=detail), & + & error=error & + & ) + +IF (ALLOCATED(error)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & + & ' with following message: '//CHAR_LF//error%message) +END IF + +END PROCEDURE toml_get_from_filename + +END SUBMODULE GetMethods From ba9e1dcf90fc2a60d579228b076eb3e8622a6e59 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 15:33:28 +0900 Subject: [PATCH 012/117] commiting one by one --- .../AbstractField/src/AbstractField_Class.F90 | 56 ++++++- .../src/AbstractField_Class@Methods.F90 | 141 +++++++++++++++--- 2 files changed, 168 insertions(+), 29 deletions(-) diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index 0da8ea0e8..f3c45f064 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -53,6 +53,8 @@ MODULE AbstractField_Class PUBLIC :: AbstractFieldExport PUBLIC :: AbstractFieldDeallocate PUBLIC :: FIELD_TYPE_NUMBER +PUBLIC :: SetAbstractFieldParam +PUBLIC :: AbstractFieldCheckEssentialParam !---------------------------------------------------------------------------- ! AbstractField_ @@ -180,11 +182,11 @@ MODULE AbstractField_Class ! summary: This routine check the essential parameters in param. ABSTRACT INTERFACE - SUBROUTINE aField_checkEssentialParam(obj, param) + SUBROUTINE aField_CheckEssentialParam(obj, param) IMPORT :: AbstractField_, ParameterList_ CLASS(AbstractField_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE aField_checkEssentialParam + END SUBROUTINE aField_CheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- @@ -204,6 +206,50 @@ SUBROUTINE aField_Initiate1(obj, param, dom) END SUBROUTINE aField_Initiate1 END INTERFACE +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE AbstractFieldCheckEssentialParam(obj, param, prefix) + CLASS(AbstractField_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), INTENT(IN) :: prefix + END SUBROUTINE AbstractFieldCheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! SetAbstractFieldParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-04 +! summary: Set AbstractField_ parameters + +INTERFACE + MODULE SUBROUTINE SetAbstractFieldParam(param, prefix, name, engine, fieldType, & + & comm, local_n, global_n) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: prefix + !! prefix + CHARACTER(*), INTENT(IN) :: name + !! name of the variable + CHARACTER(*), INTENT(IN) :: engine + !! name of the engine + INTEGER(I4B), OPTIONAL, INTENT(IN) :: fieldType + !! field type + INTEGER(I4B), OPTIONAL, INTENT(IN) :: comm + !! communication group + !! Only needed for parallel environment + INTEGER(I4B), OPTIONAL, INTENT(IN) :: local_n + !! local size of scalar field on each processor + !! Only needed for parallel environment + INTEGER(I4B), OPTIONAL, INTENT(IN) :: global_n + !! global size of scalar field on distributed on processors + !! Only needed for parallel environment + END SUBROUTINE SetAbstractFieldParam +END INTERFACE + !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- @@ -614,7 +660,7 @@ END FUNCTION aField_GetTotalFaceDOF END INTERFACE !---------------------------------------------------------------------------- -! GetTotalCellDOF +! GetTotalCellDOF !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -637,10 +683,10 @@ END FUNCTION aField_GetTotalCellDOF ! date: 2023-09-22 ! summary: Returns true if the field is constant INTERFACE - MODULE FUNCTION aField_isConstant(obj) RESULT(ans) + MODULE FUNCTION aField_IsConstant(obj) RESULT(ans) CLASS(AbstractField_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aField_isConstant + END FUNCTION aField_IsConstant END INTERFACE END MODULE AbstractField_Class diff --git a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 index 18873ef1e..096fc12ed 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 @@ -16,10 +16,83 @@ SUBMODULE(AbstractField_Class) Methods USE BaseMethod -USE FPL_Method, ONLY: GetValue +USE FPL_Method IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractFieldCheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "AbstractFieldCheckEssentialParam()" +TYPE(String) :: astr +TYPE(String), ALLOCATABLE :: essentialParam(:) +INTEGER(I4B) :: ii + +astr = "/name/engine/fieldType/comm/local_n/global_n" +CALL astr%Split(essentialParam, sep="/") +CALL CheckEssentialParam( & + & obj=param, & + & keys=essentialParam, & + & prefix=prefix, & + & myName=myName, & + & modName=modName) +! INFO: CheckEssentialParam param is defined in easifemClasses FPL_Method + +IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" + END DO + DEALLOCATE (essentialParam) +END IF +astr = "" +END PROCEDURE AbstractFieldCheckEssentialParam + +!---------------------------------------------------------------------------- +! SetScalarFieldParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetAbstractFieldParam +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr +CHARACTER(*), PARAMETER :: myName="SetAbstractFieldParam()" + +sublist => NULL() + +ierr = param%GetSubList(key=prefix, sublist=sublist) +sublist => param%NewSubList(key=prefix) + +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF + +CALL Set(obj=sublist, datatype="Char", prefix=prefix, key="name", VALUE=name) + +CALL Set(obj=sublist, datatype="Char", prefix=prefix, key="engine", & + & VALUE=engine) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="fieldType", & + & VALUE=input(option=fieldType, default=FIELD_TYPE_NORMAL)) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="comm", & + & VALUE=input(option=fieldType, default=0_I4B)) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="local_n", & + & VALUE=input(option=local_n, default=0_I4B)) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="global_n", & + & VALUE=input(option=global_n, default=0_I4B)) + +sublist => NULL() +END PROCEDURE SetAbstractFieldParam + !---------------------------------------------------------------------------- ! Display !---------------------------------------------------------------------------- @@ -85,18 +158,38 @@ MODULE PROCEDURE AbstractFieldInitiate CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This routine is under development') -CALL obj%DEALLOCATE() -CALL obj%CheckEssentialParam(param) +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr + +! main +sublist => NULL() +ierr = param%GetSubList(key=prefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +! NOTE: We should not call deallocate in abstract classes. +! This is because, in concrete classes we may set some +! parameters before calling this method. +! All those parameters will be gone if we call deallocate +! here. +! CALL obj%DEALLOCATE() + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF + obj%isInitiated = .TRUE. -CALL GetValue(obj=param, prefix=prefix, key="fieldType", VALUE=obj%fieldType) -CALL GetValue(obj=param, prefix=prefix, key="name", VALUE=obj%name) -CALL GetValue(obj=param, prefix=prefix, key="engine", VALUE=obj%engine) -CALL GetValue(obj=param, prefix=prefix, key="comm", VALUE=obj%comm) -CALL GetValue(obj=param, prefix=prefix, key="global_n", VALUE=obj%global_n) -CALL GetValue(obj=param, prefix=prefix, key="local_n", VALUE=obj%local_n) +CALL GetValue(obj=sublist, prefix=prefix, key="fieldType", VALUE=obj%fieldType) +CALL GetValue(obj=sublist, prefix=prefix, key="name", VALUE=obj%name) +CALL GetValue(obj=sublist, prefix=prefix, key="engine", VALUE=obj%engine) +CALL GetValue(obj=sublist, prefix=prefix, key="comm", VALUE=obj%comm) +CALL GetValue(obj=sublist, prefix=prefix, key="global_n", VALUE=obj%global_n) +CALL GetValue(obj=sublist, prefix=prefix, key="local_n", VALUE=obj%local_n) obj%domain => dom +sublist => NULL() END PROCEDURE AbstractFieldInitiate !---------------------------------------------------------------------------- @@ -539,10 +632,10 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_GetTotalPhysicalVars - CHARACTER(*), PARAMETER :: myName="aField_GetTotalPhysicalVars()" - CALL e%RaiseError(modName //'::'//myName// ' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& - & 'child classes') +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalPhysicalVars()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') END PROCEDURE aField_GetTotalPhysicalVars !---------------------------------------------------------------------------- @@ -596,7 +689,7 @@ MODULE PROCEDURE aField_GetTotalDOF CHARACTER(*), PARAMETER :: myName = "aField_GetTotalDOF()" CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' // & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & & ' child classes') END PROCEDURE aField_GetTotalDOF @@ -606,8 +699,8 @@ MODULE PROCEDURE aField_GetTotalVertexDOF CHARACTER(*), PARAMETER :: myName = "aField_GetTotalVertexDOF()" -CALL e%RaiseError(modName //'::'//myName// ' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& & 'child classes') END PROCEDURE aField_GetTotalVertexDOF @@ -617,8 +710,8 @@ MODULE PROCEDURE aField_GetTotalEdgeDOF CHARACTER(*), PARAMETER :: myName = "aField_GetTotalEdgeDOF()" -CALL e%RaiseError(modName //'::'//myName// ' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& & 'child classes') END PROCEDURE aField_GetTotalEdgeDOF @@ -628,8 +721,8 @@ MODULE PROCEDURE aField_GetTotalFaceDOF CHARACTER(*), PARAMETER :: myName = "aField_GetTotalFaceDOF()" -CALL e%RaiseError(modName //'::'//myName// ' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& & 'child classes') END PROCEDURE aField_GetTotalFaceDOF @@ -639,8 +732,8 @@ MODULE PROCEDURE aField_GetTotalCellDOF CHARACTER(*), PARAMETER :: myName = "aField_GetTotalCellDOF()" -CALL e%RaiseError(modName //'::'//myName// ' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by ' //& +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& & 'child classes') END PROCEDURE aField_GetTotalCellDOF From 824c34e1bf113abd58cc5c5cab12aa3e7adf5857 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 15:33:36 +0900 Subject: [PATCH 013/117] Updates in AbstractMeshField_Class --- .../AbstractFile/src/AbstractFile_Class.F90 | 203 ++- .../src/AbstractLinSolver.toml | 57 + .../src/AbstractLinSolver2.toml | 38 + .../src/AbstractLinSolverParam.F90 | 41 +- .../src/AbstractLinSolver_Class.F90 | 385 ++++-- .../src/AbstractMeshField_Class.F90 | 6 +- .../src/AbstractNodeField_Class.F90 | 25 + src/modules/BoundaryCondition/CMakeLists.txt | 23 + .../src/BoundaryCondition.F90 | 24 + src/modules/CMakeLists.txt | 9 + src/modules/Domain/src/Domain_Class.F90 | 34 +- .../src/ExceptionHandler_Class.F90 | 27 +- src/modules/FPL/src/FPL_Method.F90 | 133 ++ src/modules/FacetElement/CMakeLists.txt | 19 +- src/modules/FieldFactory/src/FieldFactory.F90 | 21 +- .../FortranFile/src/FortranFile_Class.F90 | 125 +- src/modules/GmshAPI/CMakeLists.txt | 9 +- src/modules/GmshAPI/src/GmshFLTK_Class.F90 | 92 +- .../GmshAPI/src/GmshGraphics_Class.F90 | 2 - .../src/GmshInterface/GmshInterface.F90 | 2 +- .../src/GmshInterface/GmshModelGeoMesh.inc | 145 ++- .../GmshAPI/src/GmshModelGeoMesh_Class.F90 | 298 +++-- .../GmshAPI/src/GmshModelGeo_Class.F90 | 143 +-- .../GmshAPI/src/GmshModelMesh_Class.F90 | 6 +- src/modules/GmshAPI/src/GmshModel_Class.F90 | 55 +- src/modules/GmshAPI/src/GmshOnelab_Class.F90 | 122 +- src/modules/GmshAPI/src/GmshOption_Class.F90 | 126 +- .../GmshAPI/src/GmshStructuredMesh_Class.F90 | 1114 +++++++++++++++++ src/modules/GmshAPI/src/Gmsh_Class.F90 | 4 +- .../src/NoGmsh/Gmsh_Class.F90} | 25 +- src/modules/LinSolver/src/LinSolver_Class.F90 | 218 +--- src/modules/MSHFile/src/MSHFile_Class.F90 | 18 +- .../MatrixField/src/MatrixField_Class.F90 | 2 +- src/modules/Mesh/src/Mesh_Class.F90 | 4 +- .../MeshSelection/src/MeshSelection.toml | 44 + .../MeshSelection/src/MeshSelection_Class.F90 | 210 +++- .../src/MixedFiniteElement_Class.F90 | 1 + src/modules/NeumannBC/src/NeumannBC_Class.F90 | 112 +- src/modules/NitscheBC/src/NitscheBC_Class.F90 | 156 +-- .../STScalarField/src/STScalarField_Class.F90 | 377 +++--- .../src/STScalarFieldLis_Class.F90 | 330 +++-- .../STVectorField/src/STVectorField_Class.F90 | 408 +++--- .../ScalarField/src/ScalarField_Class.F90 | 75 +- .../src/ScalarFieldLis_Class.F90 | 232 ++-- .../TxtFile/src/ConstructorMethods.inc | 93 -- src/modules/TxtFile/src/GetMethods.inc | 73 -- src/modules/TxtFile/src/ReadMethods.inc | 292 ----- src/modules/TxtFile/src/SetMethods.inc | 47 - src/modules/TxtFile/src/TxtFile_Class.F90 | 1029 +++++++++++++-- src/modules/TxtFile/src/WriteMethods.inc | 381 ------ src/modules/UserFunction/src/UseFunction.toml | 16 + .../UserFunction/src/UserFunction_Class.F90 | 394 ++++-- src/modules/Vector/src/Vector_Class.F90 | 70 +- .../VectorField/src/VectorField_Class.F90 | 213 ++-- .../easifemClasses/src/easifemClasses.F90 | 10 +- .../AbstractLinSolver_Class@GetMethods.F90 | 146 +++ .../src/AbstractLinSolver_Class@IOMethods.F90 | 395 +++++- .../AbstractLinSolver_Class@SetMethods.F90 | 557 +++++---- ...ractMeshField_Class@ConstructorMethods.F90 | 6 +- .../src/AbstractNodeField_Class@Methods.F90 | 40 +- src/submodules/CMakeLists.txt | 3 + .../src/Domain_Class@ConstructorMethods.F90 | 4 +- .../Domain/src/Domain_Class@GetMethods.F90 | 14 +- .../ExceptionHandler_Class@Constructor.F90 | 4 +- .../FortranFile_Class@ConstructorMethods.F90 | 49 +- src/submodules/LinSolver/src/LIS_SOLVE.inc | 2 +- .../src/LinSolver_Class@GetMethods.F90 | 35 +- .../src/LinSolver_Class@IOMethods.F90 | 4 +- .../src/LinSolver_Class@SetMethods.F90 | 229 +--- .../src/LinSolver_Class@SolveMethods.F90 | 12 +- .../LinSolverLis_Class@ConstructorMethods.F90 | 2 +- .../src/LinSolverLis_Class@SolveMethods.F90 | 2 +- .../src/MSHFile_Class@ConstructorMethods.F90 | 41 +- .../MSHFile/src/MSHFile_Class@IOMethods.F90 | 599 +++++---- .../MSHFile/src/mshElements_Class@Methods.F90 | 118 +- .../MSHFile/src/mshEntity_Class@Methods.F90 | 350 ++++-- .../MSHFile/src/mshFormat_Class@Methods.F90 | 48 +- .../MSHFile/src/mshNodes_Class@Methods.F90 | 118 +- .../src/mshPhysicalNames_Class@Methods.F90 | 88 +- .../Mesh/src/Mesh_Class@ShapeDataMethods.F90 | 52 +- ...MeshSelection_Class@ConstructorMethods.F90 | 213 +++- .../src/MeshSelection_Class@GetMethods.F90 | 8 + .../MeshSelection_Class@GetNodeNumMethods.F90 | 98 +- .../src/MeshSelection_Class@IOMethods.F90 | 980 ++++++++++----- .../src/MeshSelection_Class@SetMethods.F90 | 110 +- .../NeumannBC_Class@ConstructorMethods.F90 | 48 +- .../src/NeumannBC_Class@GetMethods.F90 | 8 + .../src/NeumannBC_Class@IOMethods.F90 | 98 ++ .../NitscheBC_Class@ConstructorMethods.F90 | 41 - .../src/NitscheBC_Class@GetMethods.F90 | 46 +- .../src/NitscheBC_Class@IOMethods.F90 | 98 ++ .../src/NitscheBC_Class@SetMethods.F90 | 1 - ...STScalarField_Class@ConstructorMethods.F90 | 135 +- .../src/STScalarField_Class@GetMethods.F90 | 114 +- .../src/STScalarFieldLis_Class@SetMethods.F90 | 304 ++--- ...alarMeshField_Class@ConstructorMethods.F90 | 2 +- ...nsorMeshField_Class@ConstructorMethods.F90 | 2 +- ...STVectorField_Class@ConstructorMethods.F90 | 145 ++- ...ctorMeshField_Class@ConstructorMethods.F90 | 2 +- .../ScalarField_Class@ConstructorMethods.F90 | 127 +- ...alarMeshField_Class@ConstructorMethods.F90 | 2 +- ...nsorMeshField_Class@ConstructorMethods.F90 | 2 +- .../TxtFile/src/TxtFile_Class@ReadMethods.F90 | 41 +- .../UserFunction_Class@ConstructorMethods.F90 | 283 ++++- .../src/UserFunction_Class@GetMethods.F90 | 376 +++++- .../src/UserFunction_Class@IOMethods.F90 | 581 ++++++--- .../src/UserFunction_Class@SetMethods.F90 | 22 +- .../Vector/src/Vector_Class@SetMethods.F90 | 264 ++-- .../VectorField_Class@ConstructorMethods.F90 | 109 +- ...ctorMeshField_Class@ConstructorMethods.F90 | 2 +- 110 files changed, 9973 insertions(+), 5325 deletions(-) create mode 100644 src/modules/AbstractLinSolver/src/AbstractLinSolver.toml create mode 100644 src/modules/AbstractLinSolver/src/AbstractLinSolver2.toml create mode 100644 src/modules/BoundaryCondition/src/BoundaryCondition.F90 create mode 100644 src/modules/GmshAPI/src/GmshStructuredMesh_Class.F90 rename src/modules/{TxtFile/src/EnquireMethods.inc => GmshAPI/src/NoGmsh/Gmsh_Class.F90} (63%) create mode 100644 src/modules/MeshSelection/src/MeshSelection.toml delete mode 100644 src/modules/TxtFile/src/ConstructorMethods.inc delete mode 100644 src/modules/TxtFile/src/GetMethods.inc delete mode 100644 src/modules/TxtFile/src/ReadMethods.inc delete mode 100644 src/modules/TxtFile/src/SetMethods.inc delete mode 100644 src/modules/TxtFile/src/WriteMethods.inc create mode 100644 src/modules/UserFunction/src/UseFunction.toml diff --git a/src/modules/AbstractFile/src/AbstractFile_Class.F90 b/src/modules/AbstractFile/src/AbstractFile_Class.F90 index c344d91e1..54e114e0b 100644 --- a/src/modules/AbstractFile/src/AbstractFile_Class.F90 +++ b/src/modules/AbstractFile/src/AbstractFile_Class.F90 @@ -1,39 +1,39 @@ -! This program is a part of EASIFEM library +! 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 +! 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, +! 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 +! along with thIs program. If not, see ! !> authors: Vikas Sharma, Ph. D. ! date: 2 May 2021 ! summary: module for I/O defines the base file type object. ! -! The developement of this module is inspired from the -! `FileType_Base.F90` of Futility package. The original source is located at +! The developement of thIs module Is inspired from the +! `FileType_Base.F90` of Futility package. The original source Is located at ! https://github.com/CASL/Futility/blob/master/src/FileType_Base.F90. ! ! The original code has been modified as per the code-standard of easifem ! library. ! -! This type is an abstract type, so it has no specific implementation. It -! exists only to provide a base for the extended types. It specifies the +! ThIs type Is an abstract type, so it has no specific implementation. It +! exIsts only to provide a base for the extended types. It specifies the ! maximum lengths for the file path, name, and extension, some basic -! attributes of a file such as whether or not it is open and also if it is +! attributes of a file such as whether or not it Is open and also if it Is ! open for reading or writing are provided. Methods to interface to all ! attributes are also provided. ! -! Since this is an abstract type, it has no specific implementation so see +! Since thIs Is an abstract type, it has no specific implementation so see ! one of it's extended types for examples on how it should be used. MODULE AbstractFile_Class @@ -42,12 +42,16 @@ MODULE AbstractFile_Class USE ExceptionHandler_Class, ONLY: e IMPLICIT NONE PRIVATE -!List of Public Members +!LIst of Public Members CHARACTER(*), PARAMETER :: modName = 'AbstractFile_Class' INTEGER(I4B), PARAMETER :: maxStrLen = 256 !! TYPE(ExceptionHandler_), PRIVATE :: e !! The exception handler for the object - !! List of type bound procedures (methods) for the Base File Type object + !! LIst of type bound procedures (methods) for the Base File Type object + +PUBLIC :: AbstractFile_ +PUBLIC :: AbstractFilePointer_ +PUBLIC :: AbstractFileDeallocate !---------------------------------------------------------------------------- ! AbstractFile_ @@ -55,7 +59,7 @@ MODULE AbstractFile_Class !> authors: Vikas Sharma, Ph. D. ! date: 2 May 2021 -! summary: This is an abstract type which means it has no basic implementation +! summary: A n abstract type which means it has no basic implementation TYPE, ABSTRACT :: AbstractFile_ PRIVATE @@ -72,53 +76,50 @@ MODULE AbstractFile_Class TYPE(String) :: ext !! The extension of the file name LOGICAL(LGT) :: openstat = .FALSE. - !! Whether or not the file is open + !! Whether or not the file Is open LOGICAL(LGT) :: EOFstat = .FALSE. !! Whether or not the end of file has been reached LOGICAL(LGT) :: readstat = .FALSE. - !! Whether or not the file is open for reading + !! Whether or not the file Is open for reading LOGICAL(LGT) :: writestat = .FALSE. - !! Whether or not the file is open for writing + !! Whether or not the file Is open for writing CONTAINS PRIVATE - !! - !! ConstructorMethods - !! + ! CONSTRUCTOR:1 + ! ConstructorMethods PROCEDURE, PUBLIC, PASS(Obj) :: DEALLOCATE => AbstractFileDeallocate - !! - !! @SetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: setFilePath => aFile_setFilePath - PROCEDURE, PUBLIC, PASS(obj) :: setFileName => aFile_setFileName - PROCEDURE, PUBLIC, PASS(obj) :: setFileExt => aFile_setFileExt - PROCEDURE, PUBLIC, PASS(obj) :: setEOFstat => aFile_setEOFStat - PROCEDURE, PUBLIC, PASS(obj) :: setOpenStat => aFile_setOpenStat - PROCEDURE, PUBLIC, PASS(obj) :: setReadStat => aFile_setReadStat - PROCEDURE, PUBLIC, PASS(obj) :: setWriteStat => aFile_setWriteStat - !! - !! @GetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: getFilePath => aFile_getFilePath - PROCEDURE, PUBLIC, PASS(obj) :: getFileName => aFile_getFileName - PROCEDURE, PUBLIC, PASS(obj) :: getFileExt => aFile_getFileExt - PROCEDURE, PUBLIC, PASS(obj) :: getFileParts => aFile_getFileParts - !! - !! @EnquireMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: isOpen => aFile_isOpen - PROCEDURE, PUBLIC, PASS(obj) :: isEOF => aFile_isEOF - PROCEDURE, PUBLIC, PASS(obj) :: isRead => aFile_isRead - PROCEDURE, PUBLIC, PASS(obj) :: isWrite => aFile_isWrite - !! - !! Deferred Methods - !! + + ! Set: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(obj) :: SetFilePath => aFile_SetFilePath + PROCEDURE, PUBLIC, PASS(obj) :: SetFileName => aFile_SetFileName + PROCEDURE, PUBLIC, PASS(obj) :: SetFileExt => aFile_SetFileExt + PROCEDURE, PUBLIC, PASS(obj) :: SetEOFstat => aFile_SetEOFStat + PROCEDURE, PUBLIC, PASS(obj) :: SetOpenStat => aFile_SetOpenStat + PROCEDURE, PUBLIC, PASS(obj) :: SetReadStat => aFile_SetReadStat + PROCEDURE, PUBLIC, PASS(obj) :: SetWriteStat => aFile_SetWriteStat + + ! Get: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetFilePath => aFile_GetFilePath + PROCEDURE, PUBLIC, PASS(obj) :: GetFileName => aFile_GetFileName + PROCEDURE, PUBLIC, PASS(obj) :: GetFileExt => aFile_GetFileExt + PROCEDURE, PUBLIC, PASS(obj) :: GetFileParts => aFile_GetFileParts + + ! Get: + ! @EnquireMethods + PROCEDURE, PUBLIC, PASS(obj) :: IsOpen => aFile_IsOpen + PROCEDURE, PUBLIC, PASS(obj) :: IsEOF => aFile_IsEOF + PROCEDURE, PUBLIC, PASS(obj) :: IsRead => aFile_IsRead + PROCEDURE, PUBLIC, PASS(obj) :: IsWrite => aFile_IsWrite + + ! Set: + ! Deferred Methods PROCEDURE(aFile_open), PUBLIC, DEFERRED, PASS(obj) :: OPEN PROCEDURE(aFile_close), PUBLIC, DEFERRED, PASS(obj) :: CLOSE - PROCEDURE(aFile_delete), PUBLIC, DEFERRED, PASS(obj) :: delete + PROCEDURE(aFile_Delete), PUBLIC, DEFERRED, PASS(obj) :: Delete END TYPE AbstractFile_ -PUBLIC :: AbstractFile_ - !---------------------------------------------------------------------------- ! AbstractFilePointer_ !---------------------------------------------------------------------------- @@ -127,8 +128,6 @@ MODULE AbstractFile_Class CLASS(AbstractFile_), POINTER :: ptr => NULL() END TYPE AbstractFilePointer_ -PUBLIC :: AbstractFilePointer_ - !---------------------------------------------------------------------------- ! Dealalocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -138,16 +137,14 @@ MODULE AbstractFile_Class ! summary: Deallocate the data stored in the file INTERFACE - MODULE SUBROUTINE AbstractFileDeallocate(obj, delete) + MODULE SUBROUTINE AbstractFileDeallocate(obj, Delete) CLASS(AbstractFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete END SUBROUTINE AbstractFileDeallocate END INTERFACE -PUBLIC :: AbstractFileDeallocate - !---------------------------------------------------------------------------- -! setFilePath@SetMethods +! SetFilePath@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -155,14 +152,14 @@ END SUBROUTINE AbstractFileDeallocate ! summary: Set the path of file INTERFACE - MODULE SUBROUTINE aFile_setFilePath(obj, path) + MODULE SUBROUTINE aFile_SetFilePath(obj, path) CLASS(AbstractFile_), INTENT(INOUT) :: obj TYPE(String), INTENT(IN) :: path - END SUBROUTINE aFile_setFilePath + END SUBROUTINE aFile_SetFilePath END INTERFACE !---------------------------------------------------------------------------- -! setFileName@SetMethods +! SetFileName@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -170,14 +167,14 @@ END SUBROUTINE aFile_setFilePath ! summary: Set the file name INTERFACE - MODULE SUBROUTINE aFile_setFileName(obj, fileName) + MODULE SUBROUTINE aFile_SetFileName(obj, fileName) CLASS(AbstractFile_), INTENT(INOUT) :: obj TYPE(String), INTENT(IN) :: fileName - END SUBROUTINE aFile_setFileName + END SUBROUTINE aFile_SetFileName END INTERFACE !---------------------------------------------------------------------------- -! setFileExt@SetMethods +! SetFileExt@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -185,14 +182,14 @@ END SUBROUTINE aFile_setFileName ! summary: Set the file extension INTERFACE - MODULE SUBROUTINE aFile_setFileExt(obj, Ext) + MODULE SUBROUTINE aFile_SetFileExt(obj, Ext) CLASS(AbstractFile_), INTENT(INOUT) :: obj TYPE(String), INTENT(IN) :: Ext - END SUBROUTINE aFile_setFileExt + END SUBROUTINE aFile_SetFileExt END INTERFACE !---------------------------------------------------------------------------- -! setEOFstat@SetMethods +! SetEOFstat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -200,14 +197,14 @@ END SUBROUTINE aFile_setFileExt ! summary: Set the end of file status of file INTERFACE - MODULE SUBROUTINE aFile_setEOFstat(obj, stat) + MODULE SUBROUTINE aFile_SetEOFstat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setEOFstat + END SUBROUTINE aFile_SetEOFstat END INTERFACE !---------------------------------------------------------------------------- -! setOpenStat@SetMethods +! SetOpenStat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -215,14 +212,14 @@ END SUBROUTINE aFile_setEOFstat ! summary: Set the openStat INTERFACE - MODULE SUBROUTINE aFile_setOpenStat(obj, stat) + MODULE SUBROUTINE aFile_SetOpenStat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setOpenStat + END SUBROUTINE aFile_SetOpenStat END INTERFACE !---------------------------------------------------------------------------- -! setReadStat@SetMethods +! SetReadStat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -230,14 +227,14 @@ END SUBROUTINE aFile_setOpenStat ! summary: Set the readStat INTERFACE - MODULE SUBROUTINE aFile_setReadStat(obj, stat) + MODULE SUBROUTINE aFile_SetReadStat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setReadStat + END SUBROUTINE aFile_SetReadStat END INTERFACE !---------------------------------------------------------------------------- -! setWriteStat@SetMethods +! SetWriteStat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -245,14 +242,14 @@ END SUBROUTINE aFile_setReadStat ! summary: Set the writeStat INTERFACE - MODULE SUBROUTINE aFile_setWriteStat(obj, stat) + MODULE SUBROUTINE aFile_SetWriteStat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setWriteStat + END SUBROUTINE aFile_SetWriteStat END INTERFACE !---------------------------------------------------------------------------- -! getFilePath@GetMethods +! GetFilePath@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -260,14 +257,14 @@ END SUBROUTINE aFile_setWriteStat ! summary: Returns the path of the file INTERFACE - MODULE FUNCTION aFile_getFilePath(obj) RESULT(path) + MODULE FUNCTION aFile_GetFilePath(obj) RESULT(path) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String) :: path - END FUNCTION aFile_getFilePath + END FUNCTION aFile_GetFilePath END INTERFACE !---------------------------------------------------------------------------- -! getFileName@GetMethods +! GetFileName@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -275,14 +272,14 @@ END FUNCTION aFile_getFilePath ! summary: Returns the name of the file INTERFACE - MODULE FUNCTION aFile_getFileName(obj) RESULT(fileName) + MODULE FUNCTION aFile_GetFileName(obj) RESULT(fileName) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String) :: fileName - END FUNCTION aFile_getFileName + END FUNCTION aFile_GetFileName END INTERFACE !---------------------------------------------------------------------------- -! getFileExt@GetMethods +! GetFileExt@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -290,14 +287,14 @@ END FUNCTION aFile_getFileName ! summary: Returns the extension of the file INTERFACE - MODULE FUNCTION aFile_getFileExt(obj) RESULT(Ext) + MODULE FUNCTION aFile_GetFileExt(obj) RESULT(Ext) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String) :: Ext - END FUNCTION aFile_getFileExt + END FUNCTION aFile_GetFileExt END INTERFACE !---------------------------------------------------------------------------- -! getFileParts@GetMethods +! GetFileParts@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -305,46 +302,46 @@ END FUNCTION aFile_getFileExt ! summary: Returns the path, filename, and extension of the file INTERFACE - MODULE PURE SUBROUTINE aFile_getFileParts(obj, path, fileName, ext) + MODULE PURE SUBROUTINE aFile_GetFileParts(obj, path, fileName, ext) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String), INTENT(OUT) :: path TYPE(String), INTENT(OUT) :: fileName TYPE(String), INTENT(OUT) :: ext - END SUBROUTINE aFile_getFileParts + END SUBROUTINE aFile_GetFileParts END INTERFACE !---------------------------------------------------------------------------- -! isOpen@GetMethods +! IsOpen@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 8 May 2022 -! summary: Returns true if the file is open +! summary: Returns true if the file Is open INTERFACE - MODULE FUNCTION aFile_isOpen(obj) RESULT(ans) + MODULE FUNCTION aFile_IsOpen(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isOpen + END FUNCTION aFile_IsOpen END INTERFACE !---------------------------------------------------------------------------- -! isEOF@EnquireMethods +! IsEOF@EnquireMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 8 May 2022 -! summary: Returns true if the end of the file is reached +! summary: Returns true if the end of the file Is reached INTERFACE - MODULE FUNCTION aFile_isEOF(obj) RESULT(ans) + MODULE FUNCTION aFile_IsEOF(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isEOF + END FUNCTION aFile_IsEOF END INTERFACE !---------------------------------------------------------------------------- -! isRead@EnquireMethods +! IsRead@EnquireMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -352,14 +349,14 @@ END FUNCTION aFile_isEOF ! summary: Returns true if the file has read access INTERFACE - MODULE FUNCTION aFile_isRead(obj) RESULT(ans) + MODULE FUNCTION aFile_IsRead(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isRead + END FUNCTION aFile_IsRead END INTERFACE !---------------------------------------------------------------------------- -! isWrite@EnquireMethods +! IsWrite@EnquireMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -367,10 +364,10 @@ END FUNCTION aFile_isRead ! summary: Returns true if the file has write access INTERFACE - MODULE FUNCTION aFile_isWrite(obj) RESULT(ans) + MODULE FUNCTION aFile_IsWrite(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isWrite + END FUNCTION aFile_IsWrite END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/modules/AbstractLinSolver/src/AbstractLinSolver.toml b/src/modules/AbstractLinSolver/src/AbstractLinSolver.toml new file mode 100644 index 000000000..e1f492b05 --- /dev/null +++ b/src/modules/AbstractLinSolver/src/AbstractLinSolver.toml @@ -0,0 +1,57 @@ +[linSolver] +engine = "NATIVE_SERIAL" +solverName = "CG" +convergenceIn = "RESIDUAL" +convergenceType = "RELATIVE" +scale = "NONE" +maxIter = 1000 +krylovSubspaceSize = 50 +bicgstab_ell = 2 +atol = 0.0000000099999999 +rtol = 0.0000000099999999 +relativeToRHS = false +initx_zeros = true +sor_omega = 1.8999999999999999 + +[linSolver.precondition] +option = "NO_PRECONDITION" +name = "ILU" + +[linSolver.precondition.ilu] +lfil = 5 +mbloc = 10 +fill = 5 +droptol = 0.0050000000000000 +permtol = 0.1000000000000000 +alpha = 1.0000000000000000 + +[linSolver.precondition.hybrid] +name = "SOR" +maxIter = 25 +ell = 2 +restart = 40 +tol = 0.0010000000474975 +omega = 1.5000000000000000 + +[linSolver.precondition.is] +m = 3 +p_is_alpha = 1.0000000000000000 + +[linSolver.precondition.adds] +iter = 1 +isAdditiveSchwarz = true + +[linSolver.precondition.ssor] +omega = 1.0000000000000000 + +[linSolver.precondition.sainv] +drop = 0.0500000007450581 + +[linSolver.precondition.saamg] +theta = 0.0500000007450581 +unsym = false + +[linSolver.precondition.iluc] +drop = 0.0500000007450581 +rate = 5.0000000000000000 + diff --git a/src/modules/AbstractLinSolver/src/AbstractLinSolver2.toml b/src/modules/AbstractLinSolver/src/AbstractLinSolver2.toml new file mode 100644 index 000000000..6b013efb8 --- /dev/null +++ b/src/modules/AbstractLinSolver/src/AbstractLinSolver2.toml @@ -0,0 +1,38 @@ +[linSolver] +engine = "NATIVE_SERIAL" +solverName = "CG" +convergenceIn = "RESIDUAL" +convergenceType = "RELATIVE" +scale = "NONE" +maxIter = 1000 +krylovSubspaceSize = 50 +bicgstab_ell = 2 +atol = 0.0000000099999999 +rtol = 0.0000000099999999 +relativeToRHS = false +initx_zeros = true +sor_omega = 1.8999999999999999 +"precondition.option" = "NO_PRECONDITION" +"precondition.name" = "ILU" +"precondition.ilu.lfil" = 5 +"precondition.ilu.mbloc" = 10 +"precondition.ilu.fill" = 5 +"precondition.ilu.droptol" = 0.0050000000000000 +"precondition.ilu.permtol" = 0.1000000000000000 +"precondition.ilu.alpha" = 1.0000000000000000 +"precondition.hybrid.name" = "SOR" +"precondition.hybrid.maxIter" = 25 +"precondition.hybrid.ell" = 2 +"precondition.hybrid.restart" = 40 +"precondition.hybrid.tol" = 0.0010000000474975 +"precondition.hybrid.omega" = 1.5000000000000000 +"precondition.is.m" = 3 +"precondition.is.p_is_alpha" = 1.0000000000000000 +"precondition.adds.iter" = 1 +"precondition.adds.isAdditiveSchwarz" = true +"precondition.ssor.omega" = 1.0000000000000000 +"precondition.sainv.drop" = 0.0500000007450581 +"precondition.saamg.theta" = 0.0500000007450581 +"precondition.saamg.unsym" = false +"precondition.iluc.drop" = 0.0500000007450581 +"precondition.iluc.rate" = 5.0000000000000000 diff --git a/src/modules/AbstractLinSolver/src/AbstractLinSolverParam.F90 b/src/modules/AbstractLinSolver/src/AbstractLinSolverParam.F90 index f88002b1a..5f45b9457 100644 --- a/src/modules/AbstractLinSolver/src/AbstractLinSolverParam.F90 +++ b/src/modules/AbstractLinSolver/src/AbstractLinSolverParam.F90 @@ -20,27 +20,46 @@ MODULE AbstractLinSolverParam IMPLICIT NONE PRIVATE +CHARACTER(*), PARAMETER, PUBLIC :: default_engine = "NATIVE_SERIAL" +CHARACTER(*), PARAMETER, PUBLIC :: default_solverName_char = "CG" +INTEGER(I4B), PARAMETER, PUBLIC :: default_solverName = lis_cg +CHARACTER(*), PARAMETER, PUBLIC :: default_preconditionOption_char = & + & "NO_PRECONDITION" +INTEGER(I4B), PARAMETER, PUBLIC :: default_preconditionOption = & + & NO_PRECONDITION +CHARACTER(*), PARAMETER, PUBLIC :: default_p_name_char = & + & "ILU" +INTEGER(I4B), PARAMETER, PUBLIC :: default_p_name = PRECOND_ILU + INTEGER(I4B), PARAMETER, PUBLIC :: default_convergenceIn = convergenceInRes +CHARACTER(*) , PARAMETER, PUBLIC :: default_convergenceIn_char="RESIDUAL" + INTEGER(I4B), PARAMETER, PUBLIC :: default_convergenceType & -& = relativeConvergence + & = relativeConvergence +CHARACTER(*), PARAMETER, PUBLIC :: default_convergenceType_char = & + & "RELATIVE" + INTEGER(I4B), PARAMETER, PUBLIC :: default_maxIter & -& = 1000 + & = 1000 LOGICAL(LGT), PARAMETER, PUBLIC :: default_relativeToRHS & -& = .FALSE. + & = .FALSE. INTEGER(I4B), PARAMETER, PUBLIC :: default_KrylovSubspaceSize & -& = 50 + & = 50 REAL(DFP), PARAMETER, PUBLIC :: default_rtol & -& = 1.0E-8 + & = 1.0E-8 REAL(DFP), PARAMETER, PUBLIC :: default_atol & -& = 1.0E-8 + & = 1.0E-8 REAL(DFP), PARAMETER, PUBLIC :: default_sor_omega & -& = 1.9_DFP + & = 1.9_DFP INTEGER(I4B), PARAMETER, PUBLIC :: default_bicgstab_ell = 2 INTEGER(I4B), PARAMETER, PUBLIC :: scale_none = 0 INTEGER(I4B), PARAMETER, PUBLIC :: scale_jacobi = 1 INTEGER(I4B), PARAMETER, PUBLIC :: scale_symm_diag = 2 INTEGER(I4B), PARAMETER, PUBLIC :: default_scale = scale_none +CHARACTER(*) , PARAMETER, PUBLIC :: default_scale_char = "NONE" + LOGICAL(LGT), PARAMETER, PUBLIC :: default_initx_zeros = .TRUE. + INTEGER(I4B), PARAMETER, PUBLIC :: default_ilu_lfil = 5 INTEGER(I4B), PARAMETER, PUBLIC :: default_ilu_mbloc = 10 REAL(DFP), PARAMETER, PUBLIC :: default_ilu_droptol = 0.005_DFP @@ -49,19 +68,27 @@ MODULE AbstractLinSolverParam INTEGER(I4B), PARAMETER, PUBLIC :: default_ilu_fill = 5 REAL(DFP), PARAMETER, PUBLIC :: default_ssor_omega = 1.0 + INTEGER(I4B), PARAMETER, PUBLIC :: default_hybrid_i = LIS_SOR +CHARACTER(*) , PARAMETER, PUBLIC :: default_hybrid_i_char = "SOR" INTEGER(I4B), PARAMETER, PUBLIC :: default_hybrid_maxiter = 25 REAL(DFP), PARAMETER, PUBLIC :: default_hybrid_tol = 1.0E-3 REAL(DFP), PARAMETER, PUBLIC :: default_hybrid_omega = 1.5 INTEGER(I4B), PARAMETER, PUBLIC :: default_hybrid_ell = 2 INTEGER(I4B), PARAMETER, PUBLIC :: default_hybrid_restart = 40 + REAL(DFP), PARAMETER, PUBLIC :: default_is_alpha = 1.0 INTEGER(I4B), PARAMETER, PUBLIC :: default_is_m = 3 + REAL(DFP), PARAMETER, PUBLIC :: default_sainv_drop = 0.05 + LOGICAL(LGT), PARAMETER, PUBLIC :: default_saamg_unsym = .FALSE. + REAL(DFP), PARAMETER, PUBLIC :: default_saamg_theta = 0.05 + REAL(DFP), PARAMETER, PUBLIC :: default_iluc_drop = 0.05 REAL(DFP), PARAMETER, PUBLIC :: default_iluc_rate = 5.0 + LOGICAL(LGT), PARAMETER, PUBLIC :: default_adds = .TRUE. INTEGER(I4B), PARAMETER, PUBLIC :: default_adds_iter = 1 END MODULE AbstractLinSolverParam diff --git a/src/modules/AbstractLinSolver/src/AbstractLinSolver_Class.F90 b/src/modules/AbstractLinSolver/src/AbstractLinSolver_Class.F90 index bf3be75a9..2cd2cca81 100644 --- a/src/modules/AbstractLinSolver/src/AbstractLinSolver_Class.F90 +++ b/src/modules/AbstractLinSolver/src/AbstractLinSolver_Class.F90 @@ -21,7 +21,7 @@ MODULE AbstractLinSolver_Class USE GlobalData -USE BaseType +USE BaSetype USE String_Class, ONLY: String USE FPL, ONLY: ParameterList_ USE ExceptionHandler_Class, ONLY: e @@ -29,10 +29,24 @@ MODULE AbstractLinSolver_Class USE DirichletBC_Class USE Field USE AbstractLinSolverParam +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE +PUBLIC :: AbstractLinSolverImport +PUBLIC :: AbstractLinSolverDisplay +PUBLIC :: GetAbstractLinSolverParam +PUBLIC :: AbstractLinSolverPointer_ +PUBLIC :: AbstractLinSolver_ +PUBLIC :: ExportAbstractLinSolver +PUBLIC :: AbstractLinSolverExport +PUBLIC :: AbstractLinSolverDeallocate +PUBLIC :: AbstractLinSolverImportParamFromToml +PUBLIC :: AbstractLinSolverImportFromToml +PUBLIC :: SetAbstractLinSolverParam CHARACTER(*), PARAMETER :: modName = "AbstractLinSolver_Class" +CHARACTER(*), PARAMETER :: myprefix = "AbstractLinSolver" !---------------------------------------------------------------------------- ! AbstractLinSolver_ @@ -117,38 +131,66 @@ MODULE AbstractLinSolver_Class CLASS(AbstractMatrixField_), POINTER :: Amat => NULL() !! Pointer to child of [[AbstractMatrixField_]] CONTAINS - PROCEDURE(als_checkEssentialParam), PUBLIC, DEFERRED, PASS(obj) :: & - & checkEssentialParam + PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE(als_CheckEssentialParam), PUBLIC, DEFERRED, PASS(obj) :: & + & CheckEssentialParam + !! Check essential parameters PROCEDURE(als_initiate), PUBLIC, DEFERRED, PASS(obj) :: Initiate !! Initiate the object PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => als_Deallocate !! Deallocate Data - PROCEDURE(als_set), PUBLIC, DEFERRED, PASS(obj) :: Set + + ! SET: + ! @SetMethods + PROCEDURE(als_Set), PUBLIC, DEFERRED, PASS(obj) :: Set !! Set the matrix and preconditioning matrix + PROCEDURE, PUBLIC, PASS(obj) :: SetTolerance => & + & als_SetTolerance + PROCEDURE, PUBLIC, PASS(obj) :: SetParam => als_SetParam + + ! GET: + ! @GetMethods PROCEDURE(als_solve), PUBLIC, DEFERRED, PASS(obj) :: Solve !! Solve system of linear equation - PROCEDURE(als_getLinSolverCodeFromName), DEFERRED, PUBLIC, NOPASS :: & - & getLinSolverCodeFromName - PROCEDURE(als_getLinSolverNameFromCode), DEFERRED, PUBLIC, NOPASS :: & - & getLinSolverNameFromCode + PROCEDURE(als_GetLinSolverCodeFromName), DEFERRED, PUBLIC, NOPASS :: & + & GetLinSolverCodeFromName + PROCEDURE(als_GetLinSolverNameFromCode), DEFERRED, PUBLIC, NOPASS :: & + & GetLinSolverNameFromCode + PROCEDURE, PUBLIC, PASS(obj) :: GetPreconditionOption => & + & als_GetPreconditionOption + !! Get precondition options + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => als_GetParam + !! Get paramereters from abstractlin solver + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => als_GetPrefix + !! Get the prefix + PROCEDURE, PUBLIC, PASS(obj) :: solverName_ToInteger + PROCEDURE, PUBLIC, PASS(obj) :: preconditionOption_ToInteger + PROCEDURE, PUBLIC, PASS(obj) :: convergenceIn_ToInteger + PROCEDURE, PUBLIC, PASS(obj) :: convergenceType_ToInteger + PROCEDURE, PUBLIC, PASS(obj) :: preconditionName_ToInteger + PROCEDURE, PUBLIC, PASS(obj) :: scale_ToInteger + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => als_display !! Display the content PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => als_Import !! Importing linsolver from external file + PROCEDURE, PASS(obj) :: ImportFromToml1 => als_ImportFromToml1 + PROCEDURE, PASS(obj) :: ImportFromToml2 => als_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & + & ImportFromToml2 + !! Import abstract kernel from toml + PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & + & als_ImportParamFromToml + !! Import parameters for TOML file PROCEDURE, PUBLIC, PASS(obj) :: Export => als_Export !! Exporting linsolver from external file - PROCEDURE, PUBLIC, PASS(obj) :: GetPreconditionOption => & - & als_getPreconditionOption - !! Get precondition options - PROCEDURE, PUBLIC, PASS(obj) :: setTolerance => & - & als_setTolerance - !! Set tolerance - PROCEDURE, PUBLIC, PASS(obj) :: GetParam => als_GetParam - PROCEDURE, PUBLIC, PASS(obj) :: SetParam => als_SetParam END TYPE AbstractLinSolver_ -PUBLIC :: AbstractLinSolver_ - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -157,26 +199,24 @@ MODULE AbstractLinSolver_Class CLASS(AbstractLinSolver_), POINTER :: ptr => NULL() END TYPE -PUBLIC :: AbstractLinSolverPointer_ - !---------------------------------------------------------------------------- -! checkEssentialParam +! CheckEssentialParam !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 25 Aug 2021 -! summary: This routine checks the essential parameters +! summary: This routine Checks the essential parameters ABSTRACT INTERFACE - SUBROUTINE als_checkEssentialParam(obj, param) + SUBROUTINE als_CheckEssentialParam(obj, param) IMPORT :: AbstractLinSolver_, ParameterList_ CLASS(AbstractLinSolver_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE als_checkEssentialParam + END SUBROUTINE als_CheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- -! setLinSolverParam@Constructor +! SetLinSolverParam@Constructor !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -184,7 +224,7 @@ END SUBROUTINE als_checkEssentialParam ! summary: Set linear solver parameters INTERFACE - MODULE SUBROUTINE setAbstractLinSolverParam( & + MODULE SUBROUTINE SetAbstractLinSolverParam( & & param, & & prefix, & & engine, & @@ -235,78 +275,82 @@ MODULE SUBROUTINE setAbstractLinSolverParam( & INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_name !! if preconditionOption .ne. NO_PRECONDITION !! then p_name should be present - INTEGER(I4B), OPTIONAL, INTENT(IN) :: maxIter - REAL(DFP), OPTIONAL, INTENT(IN) :: atol - REAL(DFP), OPTIONAL, INTENT(IN) :: rtol INTEGER(I4B), OPTIONAL, INTENT(IN) :: convergenceIn + !! convergence in residual or solution INTEGER(I4B), OPTIONAL, INTENT(IN) :: convergenceType - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: relativeToRHS - INTEGER(I4B), OPTIONAL, INTENT(IN) :: KrylovSubspaceSize + !! relative or absolute convergence INTEGER(I4B), OPTIONAL, INTENT(IN) :: scale !! LIS, Solver digonal scaling !! scale_none: No scaling !! scale_jacobi: jacobi scaling inv(D)Ax = inv(D)b !! scale_symm_diag: sqrt(inv(D)) A sqrt(inv(D)) x = sqrt(inv(D))b - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: initx_zeros - !! if True, then we set sol=0.0 as initial guess. + INTEGER(I4B), OPTIONAL, INTENT(IN) :: maxIter + !! maximum iteration allowed + INTEGER(I4B), OPTIONAL, INTENT(IN) :: krylovSubspaceSize + !! Size of KrylovSubspaceSize INTEGER(I4B), OPTIONAL, INTENT(IN) :: bicgstab_ell !! Needed for solver BiCGSTABL - REAL(DFP), OPTIONAL, INTENT(IN) :: sor_omega - !! The relaxation coefficient INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_lfil !! Sparsekit, ilu INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_mbloc !! Sparsekit, ilu + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_fill + !! ILU, fill-in + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_i + !! Hybrid, the linear solver, for example, SSOR, GMRES, + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_maxiter + !! Hybrid, maximum number of iterations + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_ell + !!Hybrid, The degree l of the BiCGSTAB(l) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_restart + !! Hybrid, The restart value of GMRES and Orthomin + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_is_m + !! I+S, The parameter m of $I + \alpha {S}^{m}$ + INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_adds_iter + !! default value is 1 + !! ILUT Additive Schwarz number of iteration + REAL(DFP), OPTIONAL, INTENT(IN) :: atol + !! absolute tolerance + REAL(DFP), OPTIONAL, INTENT(IN) :: rtol + !! relative tolerance + REAL(DFP), OPTIONAL, INTENT(IN) :: sor_omega + !! The relaxation coefficient + REAL(DFP), OPTIONAL, INTENT(IN) :: p_is_alpha + !! I+S, The parameter alpha of $I + \alpha {S}^{m}$ REAL(DFP), OPTIONAL, INTENT(IN) :: p_ilu_droptol !! Sparsekit, ilu REAL(DFP), OPTIONAL, INTENT(IN) :: p_ilu_permtol !! Sparsekit, ilu REAL(DFP), OPTIONAL, INTENT(IN) :: p_ilu_alpha !! Sparsekit, ilu, alpha - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_fill - !! ILU, fill-in REAL(DFP), OPTIONAL, INTENT(IN) :: p_ssor_omega !! The relaxation coefficient omega in (0.0, 2.0) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_i - !! Hybrid, the linear solver, for example, SSOR, GMRES, - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_maxiter - !! Hybrid, maximum number of iterations REAL(DFP), OPTIONAL, INTENT(IN) :: p_hybrid_tol !! Hybrid, convergence tolerance REAL(DFP), OPTIONAL, INTENT(IN) :: p_hybrid_omega !! Hybrid, The relaxation coefficient omega of the SOR !! omega should be in (0.0, 2.0) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_ell - !!Hybrid, The degree l of the BiCGSTAB(l) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_restart - !! Hybrid, The restart value of GMRES and Orthomin - REAL(DFP), OPTIONAL, INTENT(IN) :: p_is_alpha - !! I+S, The parameter alpha of $I + \alpha {S}^{m}$ - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_is_m - !! I+S, The parameter m of $I + \alpha {S}^{m}$ REAL(DFP), OPTIONAL, INTENT(IN) :: p_sainv_drop !! SA-AMG, The drop criteria + REAL(DFP), OPTIONAL, INTENT(IN) :: p_saamg_theta + !! SA-AMG, The drop criteria LOGICAL(LGT), OPTIONAL, INTENT(IN) :: p_saamg_unsym !! SA-AMG, Select the unsymmetric version !! The matrix structure must be symmetric - REAL(DFP), OPTIONAL, INTENT(IN) :: p_saamg_theta - !! SA-AMG, The drop criteria REAL(DFP), OPTIONAL, INTENT(IN) :: p_iluc_drop !! Crout ILU, default is 0.05, The drop criteria REAL(DFP), OPTIONAL, INTENT(IN) :: p_iluc_rate !! Crout ILU, The ratio of the maximum fill-in + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: relativeToRHS + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: initx_zeros + !! if True, then we Set sol=0.0 as initial guess. LOGICAL(LGT), OPTIONAL, INTENT(IN) :: p_adds !! ilut Additive Schwarz, default is true - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_adds_iter - !! default value is 1 - !! ILUT Additive Schwarz number of iteration - END SUBROUTINE setAbstractLinSolverParam + END SUBROUTINE SetAbstractLinSolverParam END INTERFACE -PUBLIC :: setAbstractLinSolverParam - !---------------------------------------------------------------------------- -! getLinSolverParam@Constructor +! GetLinSolverParam@Constructor !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -314,7 +358,7 @@ END SUBROUTINE setAbstractLinSolverParam ! summary: Set linear solver parameters INTERFACE - MODULE SUBROUTINE getAbstractLinSolverParam( & + MODULE SUBROUTINE GetAbstractLinSolverParam( & & param, & & prefix, & & engine, & @@ -373,7 +417,7 @@ MODULE SUBROUTINE getAbstractLinSolverParam( & !! scale_jacobi: jacobi scaling inv(D)Ax = inv(D)b !! scale_symm_diag: sqrt(inv(D)) A sqrt(inv(D)) x = sqrt(inv(D))b LOGICAL(LGT), OPTIONAL, INTENT(OUT) :: initx_zeros - !! if True, then we set sol=0.0 as initial guess. + !! if True, then we Set sol=0.0 as initial guess. INTEGER(I4B), OPTIONAL, INTENT(OUT) :: bicgstab_ell !! Needed for solver BiCGSTABL REAL(DFP), OPTIONAL, INTENT(OUT) :: sor_omega @@ -427,11 +471,9 @@ MODULE SUBROUTINE getAbstractLinSolverParam( & INTEGER(I4B), OPTIONAL, INTENT(OUT) :: p_adds_iter !! default value is 1 !! ILUT Additive Schwarz number of iteration - END SUBROUTINE getAbstractLinSolverParam + END SUBROUTINE GetAbstractLinSolverParam END INTERFACE -PUBLIC :: getAbstractLinSolverParam - !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- @@ -482,7 +524,7 @@ END SUBROUTINE als_Solve END INTERFACE !---------------------------------------------------------------------------- -! getLinSolverCodeFromName +! GetLinSolverCodeFromName !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -490,15 +532,15 @@ END SUBROUTINE als_Solve ! summary: Get linear solver integer code from name ABSTRACT INTERFACE - FUNCTION als_getLinSolverCodeFromName(name) RESULT(Ans) + FUNCTION als_GetLinSolverCodeFromName(name) RESULT(Ans) IMPORT :: I4B CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans - END FUNCTION als_getLinSolverCodeFromName + END FUNCTION als_GetLinSolverCodeFromName END INTERFACE !---------------------------------------------------------------------------- -! getLinSolverNameFromCode@Constructor +! GetLinSolverNameFromCode@Constructor !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -506,11 +548,11 @@ END FUNCTION als_getLinSolverCodeFromName ! summary: Get the linear solver name from integer code ABSTRACT INTERFACE - FUNCTION als_getLinSolverNameFromCode(name) RESULT(Ans) + FUNCTION als_GetLinSolverNameFromCode(name) RESULT(Ans) IMPORT :: I4B INTEGER(I4B), INTENT(IN) :: name CHARACTER(15) :: ans - END FUNCTION als_getLinSolverNameFromCode + END FUNCTION als_GetLinSolverNameFromCode END INTERFACE !---------------------------------------------------------------------------- @@ -521,20 +563,14 @@ END FUNCTION als_getLinSolverNameFromCode ! date: 2023-03-15 ! summary: Display the linear solver object -INTERFACE +INTERFACE AbstractLinSolverDisplay MODULE SUBROUTINE als_Display(obj, msg, unitno) CLASS(AbstractLinSolver_), INTENT(IN) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: Unitno END SUBROUTINE als_Display -END INTERFACE - -INTERFACE AbstractLinSolverDisplay - MODULE PROCEDURE als_Display END INTERFACE AbstractLinSolverDisplay -PUBLIC :: AbstractLinSolverDisplay - !---------------------------------------------------------------------------- ! Import@Methods !---------------------------------------------------------------------------- @@ -543,19 +579,63 @@ END SUBROUTINE als_Display ! date: 25 Aug 2021 ! summary: This routine intiates the linear solver from import -INTERFACE +INTERFACE AbstractLinSolverImport MODULE SUBROUTINE als_Import(obj, hdf5, group) CLASS(AbstractLinSolver_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE als_Import -END INTERFACE - -INTERFACE AbstractLinSolverImport - MODULE PROCEDURE als_Import END INTERFACE AbstractLinSolverImport -PUBLIC :: AbstractLinSolverImport +!---------------------------------------------------------------------------- +! ImportParamFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param by reading the toml table + +INTERFACE AbstractLinSolverImportParamFromToml + MODULE SUBROUTINE als_ImportParamFromToml(obj, param, table) + CLASS(AbstractLinSolver_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE als_ImportParamFromToml +END INTERFACE AbstractLinSolverImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE AbstractLinSolverImportFromToml + MODULE SUBROUTINE als_ImportFromToml1(obj, table) + CLASS(AbstractLinSolver_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE als_ImportFromToml1 +END INTERFACE AbstractLinSolverImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE AbstractLinSolverImportFromToml + MODULE SUBROUTINE als_ImportFromToml2(obj, tomlName, afile, filename, & + & printToml) + CLASS(AbstractLinSolver_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE als_ImportFromToml2 +END INTERFACE AbstractLinSolverImportFromToml !---------------------------------------------------------------------------- ! Export@Methods @@ -565,19 +645,17 @@ END SUBROUTINE als_Import ! date: 25 Aug 2021 ! summary: This routine exports the linear solver to external file -INTERFACE +INTERFACE ExportAbstractLinSolver MODULE SUBROUTINE als_Export(obj, hdf5, group) CLASS(AbstractLinSolver_), INTENT(IN) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE als_Export -END INTERFACE - -INTERFACE ExportAbstractLinSolver - MODULE PROCEDURE als_Export END INTERFACE ExportAbstractLinSolver -PUBLIC :: ExportAbstractLinSolver +INTERFACE AbstractLinSolverExport + MODULE PROCEDURE als_Export +END INTERFACE AbstractLinSolverExport !---------------------------------------------------------------------------- ! Deallocate@Methods @@ -587,20 +665,14 @@ END SUBROUTINE als_Export ! date: 2023-03-15 ! summary: Deallocate the linear solver -INTERFACE +INTERFACE AbstractLinSolverDeallocate MODULE SUBROUTINE als_Deallocate(obj) CLASS(AbstractLinSolver_), INTENT(INOUT) :: obj END SUBROUTINE als_Deallocate -END INTERFACE - -INTERFACE AbstractLinSolverDeallocate - MODULE PROCEDURE als_Deallocate END INTERFACE AbstractLinSolverDeallocate -PUBLIC :: AbstractLinSolverDeallocate - !---------------------------------------------------------------------------- -! getPreconditionOption@Methods +! GetPreconditionOption@Methods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -608,14 +680,14 @@ END SUBROUTINE als_Deallocate ! summary: Returns the preconditionOption INTERFACE - MODULE PURE FUNCTION als_getPreconditionOption(obj) RESULT(Ans) + MODULE PURE FUNCTION als_GetPreconditionOption(obj) RESULT(Ans) CLASS(AbstractLinSolver_), INTENT(IN) :: obj INTEGER(I4B) :: ans - END FUNCTION als_getPreconditionOption + END FUNCTION als_GetPreconditionOption END INTERFACE !---------------------------------------------------------------------------- -! getPreconditionOption@Methods +! GetPreconditionOption@Methods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -623,11 +695,11 @@ END FUNCTION als_getPreconditionOption ! summary: Returns the preconditionOption INTERFACE - MODULE PURE SUBROUTINE als_setTolerance(obj, atol, rtol) + MODULE PURE SUBROUTINE als_SetTolerance(obj, atol, rtol) CLASS(AbstractLinSolver_), INTENT(INOUT) :: obj REAL(DFP), OPTIONAL, INTENT(IN) :: atol REAL(DFP), OPTIONAL, INTENT(IN) :: rtol - END SUBROUTINE als_setTolerance + END SUBROUTINE als_SetTolerance END INTERFACE !---------------------------------------------------------------------------- @@ -770,4 +842,115 @@ MODULE SUBROUTINE als_GetParam(obj, isInitiated, engine, solverName, & END SUBROUTINE als_GetParam END INTERFACE +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: Get the prefix + +INTERFACE + MODULE FUNCTION als_GetPrefix(obj) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION als_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! solverName_ToInteger@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: solver name to integer + +INTERFACE + MODULE FUNCTION solverName_ToInteger(obj, name) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION solverName_ToInteger +END INTERFACE + +!---------------------------------------------------------------------------- +! preconditionOption_ToInteger@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: solver name to integer + +INTERFACE + MODULE FUNCTION preconditionOption_ToInteger(obj, name) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION preconditionOption_ToInteger +END INTERFACE + +!---------------------------------------------------------------------------- +! convergenceIn_ToInteger@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: solver name to integer + +INTERFACE + MODULE FUNCTION convergenceIn_ToInteger(obj, name) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION convergenceIn_ToInteger +END INTERFACE + +!---------------------------------------------------------------------------- +! convergenceType_ToInteger@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: solver name to integer + +INTERFACE + MODULE FUNCTION convergenceType_ToInteger(obj, name) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION convergenceType_ToInteger +END INTERFACE + +!---------------------------------------------------------------------------- +! scale_ToInteger@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: solver name to integer + +INTERFACE + MODULE FUNCTION scale_ToInteger(obj, name) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION scale_ToInteger +END INTERFACE + +!---------------------------------------------------------------------------- +! preconditionName_ToInteger@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: solver name to integer + +INTERFACE + MODULE FUNCTION preconditionName_ToInteger(obj, name) RESULT(ans) + CLASS(AbstractLinSolver_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION preconditionName_ToInteger +END INTERFACE + END MODULE AbstractLinSolver_Class diff --git a/src/modules/AbstractMeshField/src/AbstractMeshField_Class.F90 b/src/modules/AbstractMeshField/src/AbstractMeshField_Class.F90 index 4129751a8..debce5acd 100644 --- a/src/modules/AbstractMeshField/src/AbstractMeshField_Class.F90 +++ b/src/modules/AbstractMeshField/src/AbstractMeshField_Class.F90 @@ -30,7 +30,7 @@ MODULE AbstractMeshField_Class PUBLIC :: AbstractMeshField_ PUBLIC :: AbstractMeshFieldPointer_ PUBLIC :: SetAbstractMeshFieldParam -PUBLIC :: AbstractFieldCheckEssentialParam +PUBLIC :: AbstractMeshFieldCheckEssentialParam PUBLIC :: AbstractMeshFieldDeallocate PUBLIC :: AbstractMeshFieldInitiate PUBLIC :: DEALLOCATE @@ -172,11 +172,11 @@ END SUBROUTINE aField_checkEssentialParam ! summary: This routine check the essential parameters in param. INTERFACE - MODULE SUBROUTINE AbstractFieldCheckEssentialParam(obj, prefix, param) + MODULE SUBROUTINE AbstractMeshFieldCheckEssentialParam(obj, prefix, param) CLASS(AbstractMeshField_), INTENT(IN) :: obj CHARACTER(*), INTENT(IN) :: prefix TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE AbstractFieldCheckEssentialParam + END SUBROUTINE AbstractMeshFieldCheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index 648223bc4..e26a96860 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -35,8 +35,10 @@ MODULE AbstractNodeField_Class PUBLIC :: AbstractNodeFieldSetSingle PUBLIC :: AbstractNodeFieldGetSingle PUBLIC :: AbstractNodeFieldInitiate +PUBLIC :: AbstractNodeFieldSetParam CHARACTER(*), PARAMETER :: modName = "AbstractField_Class" +CHARACTER(*), PARAMETER :: myprefix = "AbstractNodeField" !---------------------------------------------------------------------------- ! AbstractNodeField_ @@ -108,6 +110,29 @@ MODULE AbstractNodeField_Class CLASS(AbstractNodeField_), POINTER :: ptr => NULL() END TYPE AbstractNodeFieldPointer_ +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-25 +! summary: Set parameters of AbstractNodeField_ + +INTERFACE AbstractNodeFieldSetParam + MODULE SUBROUTINE anf_SetParam(obj, dof_tPhysicalVars, & + & dof_storageFMT, dof_spaceCompo, dof_timeCompo, & + & dof_tNodes, dof_names_char, tSize) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_tPhysicalVars + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_storageFMT + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_spaceCompo(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_timeCompo(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_tNodes(:) + CHARACTER(*), OPTIONAL, INTENT(IN) :: dof_names_char(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: tSize + END SUBROUTINE anf_SetParam +END INTERFACE AbstractNodeFieldSetParam + !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- diff --git a/src/modules/BoundaryCondition/CMakeLists.txt b/src/modules/BoundaryCondition/CMakeLists.txt index e69de29bb..02fc77ec3 100644 --- a/src/modules/BoundaryCondition/CMakeLists.txt +++ b/src/modules/BoundaryCondition/CMakeLists.txt @@ -0,0 +1,23 @@ +# 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}/BoundaryCondition.F90 +) + diff --git a/src/modules/BoundaryCondition/src/BoundaryCondition.F90 b/src/modules/BoundaryCondition/src/BoundaryCondition.F90 new file mode 100644 index 000000000..eb0197e40 --- /dev/null +++ b/src/modules/BoundaryCondition/src/BoundaryCondition.F90 @@ -0,0 +1,24 @@ +! 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 BoundaryCondition +USE AbstractBC_Class +USE DirichletBC_Class +USE NeumannBC_Class +USE NitscheBC_Class +PUBLIC +END MODULE BoundaryCondition diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 422069b24..101458a00 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -15,6 +15,9 @@ # along with this program. If not, see # +# fhash +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Fhash/CMakeLists.txt) + # ExceptionHandler INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ExceptionHandler/CMakeLists.txt) @@ -54,6 +57,9 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) # FPL INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FPL/CMakeLists.txt) +# Toml +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) + # Element INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Element/CMakeLists.txt) @@ -192,6 +198,9 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/NeumannBC/CMakeLists.txt) # NitscheBC INCLUDE(${CMAKE_CURRENT_LIST_DIR}/NitscheBC/CMakeLists.txt) +# BoundaryCondition +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BoundaryCondition/CMakeLists.txt) + # UserFunction INCLUDE(${CMAKE_CURRENT_LIST_DIR}/UserFunction/CMakeLists.txt) diff --git a/src/modules/Domain/src/Domain_Class.F90 b/src/modules/Domain/src/Domain_Class.F90 index 06e3cb67b..cbd6dd16c 100644 --- a/src/modules/Domain/src/Domain_Class.F90 +++ b/src/modules/Domain/src/Domain_Class.F90 @@ -233,8 +233,12 @@ MODULE Domain_Class !! This routine a pointer to [[Mesh_]] object PROCEDURE, PUBLIC, PASS(obj) :: GetDimEntityNum => Domain_GetDimEntityNum !! Returns a dim entity-num of mesh which contains the element number - PROCEDURE, PUBLIC, PASS(obj) :: GetNodeCoord => Domain_GetNodeCoord + PROCEDURE, PASS(obj) :: GetNodeCoord1 => Domain_GetNodeCoord !! This routine returns the nodal coordinate in rank2 array + PROCEDURE, PASS(obj) :: GetNodeCoord2 => Domain_GetNodeCoord2 + !! This routine returns the nodal coordinate in rank2 array + GENERIC, PUBLIC :: GetNodeCoord => GetNodeCoord1, GetNodeCoord2 + !! Generic method which returns the nodal coordinates PROCEDURE, PUBLIC, PASS(obj) :: GetNodeCoordPointer => & & Domain_GetNodeCoordPointer !! This routine returns the pointer to nodal coordinate @@ -1008,6 +1012,34 @@ MODULE SUBROUTINE Domain_GetNodeCoord(obj, nodeCoord, dim, entityNum) END SUBROUTINE Domain_GetNodeCoord END INTERFACE +!---------------------------------------------------------------------------- +! getNodeCoord@getMethod +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 23 July 2021 +! summary: This routine returns the nodal coordinates +! +!# Introduction +! - This routine returns the nodal coordinates in the form of rank2 array. +! - The nodal coordinates are in XiJ, the columns of XiJ denotes the node +! number, and the rows correspond to the component. +! - If `dim` and `tag` are absent then this routine returns the nodal +! coordinates of the entire domain +! - If `dim` and `tag` are present then the routine selects the mesh and +! returns its nodal coordinates + +INTERFACE + MODULE SUBROUTINE Domain_GetNodeCoord2(obj, nodeCoord, globalNode) + CLASS(Domain_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: nodeCoord(:, :) + !! It should be allocated by the user. + !! SIZE(nodeCoord, 1) is equal to nsd + !! Size(nodeCoord, 2) is equal to the size(globalNode) + INTEGER(I4B), INTENT(IN) :: globalNode(:) + END SUBROUTINE Domain_GetNodeCoord2 +END INTERFACE + !---------------------------------------------------------------------------- ! getNodeCoordPointer@getMethod !---------------------------------------------------------------------------- diff --git a/src/modules/ExceptionHandler/src/ExceptionHandler_Class.F90 b/src/modules/ExceptionHandler/src/ExceptionHandler_Class.F90 index 44a555d4a..67830247c 100644 --- a/src/modules/ExceptionHandler/src/ExceptionHandler_Class.F90 +++ b/src/modules/ExceptionHandler/src/ExceptionHandler_Class.F90 @@ -59,6 +59,8 @@ MODULE ExceptionHandler_Class & [.FALSE., .FALSE., .FALSE., .FALSE.] LOGICAL(LGT), PARAMETER, PUBLIC :: DEFAULT_VERBOSE_SETTINGS(4) = & & [.TRUE., .TRUE., .TRUE., .TRUE.] +PUBLIC :: copyFromSurrogate +PUBLIC :: exceptionMessage !---------------------------------------------------------------------------- ! ExceptionHandler_ @@ -87,7 +89,7 @@ MODULE ExceptionHandler_Class LOGICAL(LGT), PRIVATE :: verbose(EXCEPTION_SIZE - 1) = & & DEFAULT_VERBOSE_SETTINGS !! Logical array that allows for selective verbosity of exception types - CHARACTER(LEN=EXCEPTION_MAX_MESG_LENGTH), PRIVATE :: lastMesg = '' + CHARACTER(EXCEPTION_MAX_MESG_LENGTH), PRIVATE :: lastMesg = '' !! The last exception message that was reported TYPE(ExceptionHandler_), POINTER, PRIVATE :: surrogate => NULL() !! Surrogate exception handler to which most functions are delegated. @@ -177,12 +179,10 @@ MODULE SUBROUTINE exceptionMessage(eCode, isQuiet, isLogActive, logUnit, & LOGICAL(LGT), INTENT(INOUT) :: isQuiet LOGICAL(LGT), INTENT(IN) :: isLogActive INTEGER(I4B), INTENT(IN) :: logUnit - CHARACTER(LEN=EXCEPTION_MAX_MESG_LENGTH), INTENT(INOUT) :: mesg + CHARACTER(EXCEPTION_MAX_MESG_LENGTH), INTENT(INOUT) :: mesg END SUBROUTINE exceptionMessage END INTERFACE -PUBLIC :: exceptionMessage - !---------------------------------------------------------------------------- ! copyFromSurrogate@Constructor !---------------------------------------------------------------------------- @@ -193,8 +193,6 @@ MODULE PURE SUBROUTINE copyFromSurrogate(obj) END SUBROUTINE copyFromSurrogate END INTERFACE -PUBLIC :: copyFromSurrogate - !---------------------------------------------------------------------------- ! obj_assign_obj@Constructor !---------------------------------------------------------------------------- @@ -341,7 +339,7 @@ END SUBROUTINE setCounter_eCode INTERFACE MODULE PURE FUNCTION getLastMessage(obj) RESULT(ans) CLASS(ExceptionHandler_), INTENT(IN) :: obj - CHARACTER(LEN=EXCEPTION_MAX_MESG_LENGTH) :: ans + CHARACTER(EXCEPTION_MAX_MESG_LENGTH) :: ans END FUNCTION getLastMessage END INTERFACE @@ -554,7 +552,7 @@ END FUNCTION isStopOnError INTERFACE MODULE SUBROUTINE raiseInformation(obj, mesg) CLASS(ExceptionHandler_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: mesg + CHARACTER(*), INTENT(IN) :: mesg END SUBROUTINE raiseInformation END INTERFACE @@ -565,7 +563,7 @@ END SUBROUTINE raiseInformation INTERFACE MODULE SUBROUTINE raiseWarning(obj, mesg) CLASS(ExceptionHandler_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: mesg + CHARACTER(*), INTENT(IN) :: mesg END SUBROUTINE raiseWarning END INTERFACE @@ -576,7 +574,7 @@ END SUBROUTINE raiseWarning INTERFACE MODULE SUBROUTINE raiseDebug(obj, mesg) CLASS(ExceptionHandler_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: mesg + CHARACTER(*), INTENT(IN) :: mesg END SUBROUTINE raiseDebug END INTERFACE @@ -587,7 +585,7 @@ END SUBROUTINE raiseDebug INTERFACE MODULE SUBROUTINE raiseError(obj, mesg) CLASS(ExceptionHandler_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: mesg + CHARACTER(*), INTENT(IN) :: mesg END SUBROUTINE raiseError END INTERFACE @@ -598,9 +596,12 @@ END SUBROUTINE raiseError INTERFACE MODULE SUBROUTINE raiseFatalError(obj, mesg) CLASS(ExceptionHandler_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: mesg + CHARACTER(*), INTENT(IN) :: mesg END SUBROUTINE raiseFatalError END INTERFACE -END MODULE ExceptionHandler_Class +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- +END MODULE ExceptionHandler_Class diff --git a/src/modules/FPL/src/FPL_Method.F90 b/src/modules/FPL/src/FPL_Method.F90 index 34fa99b6c..ab16d53d2 100644 --- a/src/modules/FPL/src/FPL_Method.F90 +++ b/src/modules/FPL/src/FPL_Method.F90 @@ -42,6 +42,7 @@ MODULE FPL_Method MODULE PROCEDURE fpl_Set_Int_R1 MODULE PROCEDURE fpl_Set_Real MODULE PROCEDURE fpl_Set_Real_R1 + MODULE PROCEDURE fpl_Set_Real_R2 MODULE PROCEDURE fpl_Set_String MODULE PROCEDURE fpl_Set_Char MODULE PROCEDURE fpl_Set_Bool @@ -56,8 +57,12 @@ MODULE FPL_Method MODULE PROCEDURE fpl_GetValue2 MODULE PROCEDURE fpl_Get_Int MODULE PROCEDURE fpl_Get_Int_R1 + MODULE PROCEDURE fpl_Get_Int_IntVec MODULE PROCEDURE fpl_Get_Real MODULE PROCEDURE fpl_Get_Real_R1 + MODULE PROCEDURE fpl_Get_Real_RealVec + MODULE PROCEDURE fpl_Get_Real_R2 + MODULE PROCEDURE fpl_Get_Real_RealMatrix MODULE PROCEDURE fpl_Get_Bool MODULE PROCEDURE fpl_Get_Bool_R1 MODULE PROCEDURE fpl_Get_String @@ -231,6 +236,30 @@ END SUBROUTINE fpl_Set_Real_R1 ! fpl_Set !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Set the real vector parameter +! +!TODO: Implement fpl_Set for Real32 and Real64 +SUBROUTINE fpl_Set_Real_R2(obj, datatype, prefix, key, VALUE) + ! Define dummy variables + TYPE(ParameterList_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: prefix + CHARACTER(*), INTENT(IN) :: key + REAL(DFP), INTENT(IN) :: datatype(1, 1) + !! This argument is only to create unique interface + REAL(DFP), OPTIONAL, INTENT(IN) :: VALUE(:, :) + ! Internal variable + INTEGER(I4B) :: ierr + IF (PRESENT(VALUE)) THEN + ierr = obj%Set(key=TRIM(prefix)//"/"//TRIM(key), VALUE=VALUE) + END IF +END SUBROUTINE fpl_Set_Real_R2 + +!---------------------------------------------------------------------------- +! fpl_Set +!---------------------------------------------------------------------------- + !> author: Vikas Sharma, Ph. D. ! date: 2023-09-09 ! summary: Set the real scalar parameter @@ -401,6 +430,32 @@ END SUBROUTINE fpl_Get_Int_R1 ! GetValue !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Get the real vector parameter + +SUBROUTINE fpl_Get_Int_IntVec(obj, prefix, key, VALUE) + ! Define dummy variables + TYPE(ParameterList_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: prefix + CHARACTER(*), INTENT(IN) :: key + TYPE(IntVector_), INTENT(INOUT) :: VALUE + + ! internal variables + INTEGER(I4B), ALLOCATABLE :: value_(:) + INTEGER(I4B) :: tsize + + tsize = SIZE(VALUE) + CALL Reallocate(value_, tsize) + CALL GetValue(obj=obj, prefix=prefix, key=key, VALUE=value_) + value = IntVector(value_) + DEALLOCATE (value_) +END SUBROUTINE fpl_Get_Int_IntVec + +!---------------------------------------------------------------------------- +! GetValue +!---------------------------------------------------------------------------- + !> author: Vikas Sharma, Ph. D. ! date: 2023-09-09 ! summary: Get the real scalar parameter @@ -453,6 +508,84 @@ END SUBROUTINE fpl_Get_Real_R1 ! GetValue !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Get the real vector parameter +! +!TODO: Implement fpl_Set for Real32, Real64 + +SUBROUTINE fpl_Get_Real_RealVec(obj, prefix, key, VALUE) + ! Define dummy variables + TYPE(ParameterList_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: prefix + CHARACTER(*), INTENT(IN) :: key + TYPE(RealVector_), INTENT(INOUT) :: VALUE + + ! internal variables + REAL(DFP), ALLOCATABLE :: value_(:) + INTEGER(I4B) :: tsize + + tsize = SIZE(VALUE) + CALL Reallocate(value_, tsize) + CALL GetValue(obj=obj, prefix=prefix, key=key, VALUE=value_) + value = RealVector(value_) + DEALLOCATE (value_) +END SUBROUTINE fpl_Get_Real_RealVec + +!---------------------------------------------------------------------------- +! GetValue +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Get the real vector parameter + +SUBROUTINE fpl_Get_Real_R2(obj, prefix, key, VALUE) + ! Define dummy variables + TYPE(ParameterList_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: prefix + CHARACTER(*), INTENT(IN) :: key + REAL(DFP), INTENT(OUT) :: VALUE(:, :) + ! Internal variable + INTEGER(I4B) :: ierr + TYPE(String) :: varname + varname = TRIM(prefix)//"/"//TRIM(key) + IF (obj%isPresent(key=varname%chars())) THEN + ierr = obj%Get(key=varname%chars(), VALUE=VALUE) + END IF + varname = "" +END SUBROUTINE fpl_Get_Real_R2 + +!---------------------------------------------------------------------------- +! GetValue +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Get the real matrix parameter + +SUBROUTINE fpl_Get_Real_RealMatrix(obj, prefix, key, VALUE) + ! Define dummy variables + TYPE(ParameterList_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: prefix + CHARACTER(*), INTENT(IN) :: key + TYPE(RealMatrix_), INTENT(INOUT) :: VALUE + + ! internal variables + REAL(DFP), ALLOCATABLE :: value_(:, :) + INTEGER(I4B) :: tsize(2) + + tsize = Shape(VALUE) + CALL Reallocate(value_, tsize(1), tsize(2) ) + CALL GetValue(obj=obj, prefix=prefix, key=key, VALUE=value_) + CALL Convert(From=value_, To=VALUE) + DEALLOCATE (value_) +END SUBROUTINE fpl_Get_Real_RealMatrix + +!---------------------------------------------------------------------------- +! GetValue +!---------------------------------------------------------------------------- + !> author: Vikas Sharma, Ph. D. ! date: 2023-09-09 ! summary: Get the boolean scalar parameter diff --git a/src/modules/FacetElement/CMakeLists.txt b/src/modules/FacetElement/CMakeLists.txt index 319b5ea62..7e7cdb1be 100644 --- a/src/modules/FacetElement/CMakeLists.txt +++ b/src/modules/FacetElement/CMakeLists.txt @@ -1,5 +1,22 @@ +# 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}/FacetElement_Class.F90 -) \ No newline at end of file +) diff --git a/src/modules/FieldFactory/src/FieldFactory.F90 b/src/modules/FieldFactory/src/FieldFactory.F90 index d7b8e3ef8..2a7aef1d1 100644 --- a/src/modules/FieldFactory/src/FieldFactory.F90 +++ b/src/modules/FieldFactory/src/FieldFactory.F90 @@ -37,14 +37,14 @@ MODULE FieldFactory PUBLIC :: STScalarFieldFactory PUBLIC :: STVectorFieldFactory PUBLIC :: Initiate -public :: MeshFieldFactory +PUBLIC :: MeshFieldFactory !---------------------------------------------------------------------------- ! MeshFieldFactory !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. -! date: 2023-09-14 +! date: 2023-09-14 ! summary: This function returns child of AbstractMeshField INTERFACE @@ -199,8 +199,8 @@ END FUNCTION STVectorFieldFactory ! NOTE: This is a module routine not a Method to VectorField_ INTERFACE Initiate - MODULE SUBROUTINE VectorField_Initiate1(obj, names, spaceCompo, fieldType, & - & engine, dom) + MODULE SUBROUTINE VectorField_Initiate1(obj, names, spaceCompo, & + & fieldType, engine, dom) TYPE(VectorFieldPointer_), INTENT(INOUT) :: obj(:) !! A vector of pointer to VectorField or subclass !! NOTE: It should be allocated @@ -235,16 +235,16 @@ END SUBROUTINE VectorField_Initiate1 ! Calling intiate methods on each vector field increases the ! code repeatition. ! Therefore, we can call this method instead. This method -! will create instances of vectorfield and its subclass. -! -! INFO: This routine is same as VectorField_Initiate1 but -! here, we can set different properties to each vector field. +! will create instances of vectorfield and its subclass. +! +! INFO: This routine is same as VectorField_Initiate1 but +! here, we can set different properties to each vector field. ! ! NOTE: This is a module routine not a Method to VectorField_ INTERFACE Initiate - MODULE SUBROUTINE VectorField_Initiate2(obj, names, spaceCompo, fieldType, & - & engine, dom) + MODULE SUBROUTINE VectorField_Initiate2(obj, names, spaceCompo, & + & fieldType, engine, dom) TYPE(VectorFieldPointer_), INTENT(INOUT) :: obj(:) !! A vector of pointer to VectorField or subclass !! NOTE: It should be allocated @@ -262,5 +262,4 @@ MODULE SUBROUTINE VectorField_Initiate2(obj, names, spaceCompo, fieldType, & END SUBROUTINE VectorField_Initiate2 END INTERFACE Initiate - END MODULE FieldFactory diff --git a/src/modules/FortranFile/src/FortranFile_Class.F90 b/src/modules/FortranFile/src/FortranFile_Class.F90 index 6c94a051f..09b3d28c4 100644 --- a/src/modules/FortranFile/src/FortranFile_Class.F90 +++ b/src/modules/FortranFile/src/FortranFile_Class.F90 @@ -39,6 +39,12 @@ MODULE FortranFile_Class CHARACTER(*), PARAMETER :: hash = "#" CHARACTER(*), PARAMETER :: comma = "," INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: FortranFile_ +PUBLIC :: FortranFilePointer_ +PUBLIC :: FortranFileInitiate +PUBLIC :: FortranFileDeallocate +PUBLIC :: FortranFileBackspace +PUBLIC :: FortranFileRewind !---------------------------------------------------------------------------- ! @@ -49,86 +55,71 @@ MODULE FortranFile_Class ! update: 2021-11-07 ! summary: Datatype for handling fortran files ! -! {!pages/FortranFile_.md!} -! -! TODO -! -! Method-1 -! - name: ReadLine(obj, aline) -! - spec: Read a line in string `aline` -! -! Method-2 -! - name: ReadLines(obj, lines()) -! - spec: Read lines in string vector lines() -! -! Reference:: [[String_Method.F90]] +!{!pages/FortranFile_.md!} TYPE, EXTENDS(AbstractFile_) :: FortranFile_ PRIVATE LOGICAL(LGT) :: initstat = .FALSE. - !! file initiated or not + !! file initiated or not INTEGER(I4B) :: unitno = -1 - !! unit number + !! unit number INTEGER(I4B) :: reclval = -1 - !! record length for direct access + !! record length for direct access LOGICAL(LGT) :: formatstat = .FALSE. - !! file is formatted or not + !! file is formatted or not LOGICAL(LGT) :: accessstat = .FALSE. - !! direct or sequential access + !! direct or sequential access LOGICAL(LGT) :: newstat = .FALSE. - !! the new status of a file + !! the new status of a file LOGICAL(LGT) :: overwrite = .FALSE. - !! replace or not + !! replace or not LOGICAL(LGT) :: padstat = .FALSE. - !! Whether or not the file is being padded + !! Whether or not the file is being padded LOGICAL(LGT) :: getNewUnit = .FALSE. CHARACTER(6) :: posopt = 'ASIS ' CHARACTER(1), PUBLIC :: comment = hash CHARACTER(1), PUBLIC :: separator = " " CHARACTER(2), PUBLIC :: delimiter = "\n" - ! + CONTAINS PRIVATE - !! + + ! CONSTRUCTOR: !! @ConstructorMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: initiate => ff_initiate + PROCEDURE, PUBLIC, PASS(Obj) :: Initiate => ff_Initiate PROCEDURE, PUBLIC, PASS(Obj) :: DEALLOCATE => ff_Deallocate FINAL :: ff_final - PROCEDURE, PUBLIC, PASS(Obj) :: OPEN => ff_open - PROCEDURE, PUBLIC, PASS(Obj) :: CLOSE => ff_close - PROCEDURE, PUBLIC, PASS(Obj) :: delete => ff_delete - PROCEDURE, PUBLIC, PASS(Obj) :: BACKSPACE => ff_backspace - PROCEDURE, PUBLIC, PASS(Obj) :: REWIND => ff_rewind - !! - !! @SetMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: setStatus => ff_setStatus - !! - !! @GetMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: getUnitNo => ff_getUnitNo - PROCEDURE, PUBLIC, PASS(Obj) :: getRecLen => ff_getRecLen - !! - !! @EnquireMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: isFormatted => ff_isFormatted - PROCEDURE, PUBLIC, PASS(Obj) :: isDirect => ff_isDirect - PROCEDURE, PUBLIC, PASS(Obj) :: isPadded => ff_isPadded - PROCEDURE, PUBLIC, PASS(Obj) :: isNew => ff_isNew - PROCEDURE, PUBLIC, PASS(Obj) :: isOverwrite => ff_isOverwrite - PROCEDURE, PUBLIC, PASS(Obj) :: isInitiated => ff_isInitiated + PROCEDURE, PUBLIC, PASS(Obj) :: OPEN => ff_Open + PROCEDURE, PUBLIC, PASS(Obj) :: CLOSE => ff_Close + PROCEDURE, PUBLIC, PASS(Obj) :: Delete => ff_Delete + PROCEDURE, PUBLIC, PASS(Obj) :: BACKSPACE => ff_Backspace + PROCEDURE, PUBLIC, PASS(Obj) :: REWIND => ff_Rewind + + ! SET: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(Obj) :: SetStatus => ff_SetStatus + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(Obj) :: GetUnitNo => ff_GetUnitNo + PROCEDURE, PUBLIC, PASS(Obj) :: GetRecLen => ff_GetRecLen + + ! GET: + ! @EnquireMethods + PROCEDURE, PUBLIC, PASS(Obj) :: IsFormatted => ff_IsFormatted + PROCEDURE, PUBLIC, PASS(Obj) :: IsDirect => ff_IsDirect + PROCEDURE, PUBLIC, PASS(Obj) :: IsPadded => ff_IsPadded + PROCEDURE, PUBLIC, PASS(Obj) :: IsNew => ff_IsNew + PROCEDURE, PUBLIC, PASS(Obj) :: IsOverwrite => ff_IsOverwrite + PROCEDURE, PUBLIC, PASS(Obj) :: IsInitiated => ff_IsInitiated END TYPE FortranFile_ -PUBLIC :: FortranFile_ TYPE(FortranFile_), PUBLIC, PARAMETER :: TypeFortranFile = FortranFile_() TYPE :: FortranFilePointer_ CLASS(FortranFile_), POINTER :: ptr => NULL() END TYPE -PUBLIC :: FortranFilePointer_ - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -137,7 +128,7 @@ MODULE FortranFile_Class ! date: 19 July 2022 ! summary: Initiate the fortran file -INTERFACE +INTERFACE FortranFileInitiate MODULE SUBROUTINE ff_initiate(obj, filename, unit, status, access, form, & & position, action, pad, recl, comment, separator, delimiter) CLASS(FortranFile_), INTENT(INOUT) :: obj @@ -168,14 +159,8 @@ MODULE SUBROUTINE ff_initiate(obj, filename, unit, status, access, form, & CHARACTER(*), OPTIONAL, INTENT(IN) :: separator CHARACTER(*), OPTIONAL, INTENT(IN) :: delimiter END SUBROUTINE ff_initiate -END INTERFACE - -INTERFACE FortranFileInitiate - MODULE PROCEDURE ff_initiate END INTERFACE FortranFileInitiate -PUBLIC :: FortranFileInitiate - !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -184,19 +169,13 @@ END SUBROUTINE ff_initiate ! date: 19 July, 2022 ! summary: Clear the content of fortran file -INTERFACE +INTERFACE FortranFileDeallocate MODULE SUBROUTINE ff_Deallocate(obj, delete) CLASS(FortranFile_), INTENT(INOUT) :: obj LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete END SUBROUTINE ff_Deallocate -END INTERFACE - -INTERFACE FortranFileDeallocate - MODULE PROCEDURE ff_Deallocate END INTERFACE FortranFileDeallocate -PUBLIC :: FortranFileDeallocate - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -261,18 +240,12 @@ END SUBROUTINE ff_delete ! date: 19 July 2022 ! summary: Move one line back -INTERFACE +INTERFACE FortranFileBackspace MODULE SUBROUTINE ff_backspace(obj) CLASS(FortranFile_), INTENT(INOUT) :: obj END SUBROUTINE ff_backspace -END INTERFACE - -INTERFACE FortranFileBackspace - MODULE PROCEDURE ff_backspace END INTERFACE FortranFileBackspace -PUBLIC :: FortranFileBackspace - !---------------------------------------------------------------------------- ! Rewind@ConstructorMethods !---------------------------------------------------------------------------- @@ -281,18 +254,12 @@ END SUBROUTINE ff_backspace ! date: 19 July 2022 ! summary: Move to the begining -INTERFACE +INTERFACE FortranFileRewind MODULE SUBROUTINE ff_rewind(obj) CLASS(FortranFile_), INTENT(INOUT) :: obj END SUBROUTINE ff_rewind -END INTERFACE - -INTERFACE FortranFileRewind - MODULE PROCEDURE ff_rewind END INTERFACE FortranFileRewind -PUBLIC :: FortranFileRewind - !---------------------------------------------------------------------------- ! ff_setStatus@SetMethods !---------------------------------------------------------------------------- diff --git a/src/modules/GmshAPI/CMakeLists.txt b/src/modules/GmshAPI/CMakeLists.txt index 4536b0451..98aaddac1 100644 --- a/src/modules/GmshAPI/CMakeLists.txt +++ b/src/modules/GmshAPI/CMakeLists.txt @@ -32,5 +32,12 @@ TARGET_SOURCES( ${src_path}/GmshOnelab_Class.F90 ${src_path}/GmshOption_Class.F90 ${src_path}/Gmsh_Class.F90 + ${src_path}/GmshStructuredMesh_Class.F90 ) -ENDIF() \ No newline at end of file +ELSE() +SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +TARGET_SOURCES( + ${PROJECT_NAME} PRIVATE + ${src_path}/NoGmsh/Gmsh_Class.F90 +) +ENDIF() diff --git a/src/modules/GmshAPI/src/GmshFLTK_Class.F90 b/src/modules/GmshAPI/src/GmshFLTK_Class.F90 index 7a7b48153..b26b9ed51 100644 --- a/src/modules/GmshAPI/src/GmshFLTK_Class.F90 +++ b/src/modules/GmshAPI/src/GmshFLTK_Class.F90 @@ -24,7 +24,7 @@ MODULE GmshFLTK_Class USE ISO_C_BINDING IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "GMSHFLTK_CLASS" +CHARACTER(*), PARAMETER :: modName = "GMSHFLTK_CLASS" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(C_INT) :: cintvar @@ -94,8 +94,8 @@ END SUBROUTINE fltk_Initiate FUNCTION fltk_Initialize() RESULT(ans) INTEGER(I4B) :: ans - CALL gmshFltkInitialize(ierr); - ans = int(ierr, i4b) + CALL gmshFltkInitialize(ierr); + ans = INT(ierr, i4b) END FUNCTION fltk_Initialize !---------------------------------------------------------------------------- @@ -106,14 +106,14 @@ END FUNCTION fltk_Initialize ! < 0, wait indefinitely. First automatically create the user interface if it ! has not yet been initialized. Can only be called in the main thread. -FUNCTION fltk_Wait(time) RESULT(ans) - CLASS(*), OPTIONAL, INTENT(IN) :: time +FUNCTION fltk_Wait(time0) RESULT(ans) + CLASS(*), OPTIONAL, INTENT(IN) :: time0 INTEGER(I4B) :: ans !! CALL gmshFltkWait( & - & time=gmsh_opt_cdouble(option=time, default=-1.0_DFP), & + & time=gmsh_opt_cdouble(option=time0, default=-1.0_DFP), & & ierr=ierr) - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION fltk_Wait !---------------------------------------------------------------------------- @@ -128,7 +128,7 @@ END FUNCTION fltk_Wait FUNCTION fltk_Update() RESULT(ans) INTEGER(I4B) :: ans CALL gmshFltkUpdate(ierr) - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION fltk_Update !---------------------------------------------------------------------------- @@ -141,16 +141,16 @@ END FUNCTION fltk_Update FUNCTION fltk_Awake(action) RESULT(ans) INTEGER(I4B) :: ans - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: action + CHARACTER(*), OPTIONAL, INTENT(IN) :: action !internal - CHARACTER(LEN=maxStrLen), TARGET :: action_ + CHARACTER(maxStrLen), TARGET :: action_ !! action_ = gmsh_CString(input(option=action, default="")) !! CALL gmshFltkAwake( & & action=action_, ierr=ierr) !! - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION fltk_Awake !---------------------------------------------------------------------------- @@ -162,7 +162,7 @@ END FUNCTION fltk_Awake FUNCTION Fltk_Lock() RESULT(ans) INTEGER(I4B) :: ans CALL gmshFltkUnlock(ierr) - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_Lock !---------------------------------------------------------------------------- @@ -174,7 +174,7 @@ END FUNCTION Fltk_Lock FUNCTION Fltk_Unlock() RESULT(ans) INTEGER(I4B) :: ans CALL gmshFltkUnlock(ierr) - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_Unlock !---------------------------------------------------------------------------- @@ -188,7 +188,7 @@ END FUNCTION Fltk_Unlock FUNCTION Fltk_Run() RESULT(ans) INTEGER(I4B) :: ans CALL gmshFltkRun(ierr) - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_Run !---------------------------------------------------------------------------- @@ -202,7 +202,7 @@ FUNCTION Fltk_IsAvailable() RESULT(ans) LOGICAL(LGT) :: ans !> main cintvar = gmshFltkIsAvailable(ierr) - IF (cintvar .EQ. 1_c_int) THEN + IF (cintvar .EQ. 1_C_INT) THEN ans = .TRUE. ELSE ans = .FALSE. @@ -216,13 +216,11 @@ END FUNCTION Fltk_IsAvailable ! Select entities in the user interface. If `dim' is >= 0, return only the ! entities of the specified dimension (e.g. points if `dim' == 0). -FUNCTION Fltk_SelectEntities(dim) & - RESULT(dimTags) +FUNCTION Fltk_SelectEntities(dim) RESULT(dimTags) INTEGER(I4B), OPTIONAL, INTENT(IN) :: dim INTEGER(I4B), ALLOCATABLE :: dimTags(:, :) - ! + ! internal - ! TYPE(C_PTR) :: cptr INTEGER(C_SIZE_T) :: dimTags_n ! @@ -241,12 +239,10 @@ END FUNCTION Fltk_SelectEntities ! Select elements in the user interface. */ -FUNCTION Fltk_SelectElements() & - & RESULT(elementTags) +FUNCTION Fltk_SelectElements() RESULT(elementTags) INTEGER(I4B), ALLOCATABLE :: elementTags(:) - ! + ! internal - ! TYPE(C_PTR) :: cptr INTEGER(C_SIZE_T) :: elementTags_n ! @@ -265,9 +261,9 @@ END FUNCTION Fltk_SelectElements ! Select views in the user interface. -FUNCTION Fltk_SelectViews() & - & RESULT(viewTags) +FUNCTION Fltk_SelectViews() RESULT(viewTags) INTEGER(I4B), ALLOCATABLE :: viewTags(:) + ! internal TYPE(C_PTR) :: cptr INTEGER(C_SIZE_T) :: viewTags_n @@ -288,15 +284,14 @@ END FUNCTION Fltk_SelectViews ! Split the current window horizontally (if `how' = "h") or vertically (if ! `how' = "v"), using ratio `ratio'. If `how' = "u", restore a single window. -FUNCTION Fltk_SplitCurrentWindow(how, ratio) & - & RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: how +FUNCTION Fltk_SplitCurrentWindow(how, ratio) RESULT(ans) + CHARACTER(*), INTENT(IN) :: how CLASS(*), OPTIONAL, INTENT(IN) :: ratio INTEGER(I4B) :: ans ! ! internal values ! - CHARACTER(LEN=maxStrLen), TARGET :: how_ + CHARACTER(maxStrLen), TARGET :: how_ ! how_ = gmsh_CString(how) ! @@ -305,7 +300,7 @@ FUNCTION Fltk_SplitCurrentWindow(how, ratio) & & ratio=gmsh_opt_cdouble(option=ratio, default=0.5_DFP), & & ierr=ierr) ! - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_SplitCurrentWindow !---------------------------------------------------------------------------- @@ -316,8 +311,7 @@ END FUNCTION Fltk_SplitCurrentWindow ! of all windows. When new windows are created by splits, new windows are ! appended at the end of the list. -FUNCTION Fltk_SetCurrentWindow(windowIndex) & - & RESULT(ans) +FUNCTION Fltk_SetCurrentWindow(windowIndex) RESULT(ans) INTEGER(I4B), OPTIONAL, INTENT(IN) :: windowIndex INTEGER(I4B) :: ans !! @@ -325,7 +319,7 @@ FUNCTION Fltk_SetCurrentWindow(windowIndex) & & windowIndex=gmsh_opt_cint(option=windowIndex, default=0_I4B), & & ierr=ierr) !! - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_SetCurrentWindow !---------------------------------------------------------------------------- @@ -335,13 +329,12 @@ END FUNCTION Fltk_SetCurrentWindow ! Set a status message in the current window. If `graphics' is set, display ! the message inside the graphic window instead of the status bar. -FUNCTION Fltk_SetStatusMessage(message, graphics) & - & RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: message +FUNCTION Fltk_SetStatusMessage(message, graphics) RESULT(ans) + CHARACTER(*), INTENT(IN) :: message LOGICAL(LGT), OPTIONAL, INTENT(IN) :: graphics INTEGER(I4B) :: ans ! internal - CHARACTER(LEN=maxStrLen), TARGET :: message_ + CHARACTER(maxStrLen), TARGET :: message_ !! message_ = gmsh_CString(message) !! @@ -350,7 +343,7 @@ FUNCTION Fltk_SetStatusMessage(message, graphics) & & graphics=optval_c_bool(.FALSE., graphics), & & ierr=ierr) !! - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_SetStatusMessage !---------------------------------------------------------------------------- @@ -359,8 +352,7 @@ END FUNCTION Fltk_SetStatusMessage ! Show context window for the entity of dimension `dim' and tag `tag'. -FUNCTION Fltk_ShowContextWindow(dim, tag) & - & RESULT(ans) +FUNCTION Fltk_ShowContextWindow(dim, tag) RESULT(ans) INTEGER(I4B), INTENT(IN) :: dim, tag INTEGER(I4B) :: ans ! internal @@ -368,7 +360,7 @@ FUNCTION Fltk_ShowContextWindow(dim, tag) & & dim=gmsh_cint(dim), & & tag=gmsh_cint(tag), & & ierr=ierr) - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_ShowContextWindow !---------------------------------------------------------------------------- @@ -380,19 +372,18 @@ END FUNCTION Fltk_ShowContextWindow ! GMSH_API void gmshFltkOpenTreeItem(const char *name, ! int *ierr); -FUNCTION Fltk_OpenTreeItem(name) & - & RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: name +FUNCTION Fltk_OpenTreeItem(name) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans ! internal - CHARACTER(LEN=maxStrLen) :: name_ + CHARACTER(maxStrLen) :: name_ ! name_ = gmsh_CString(name) ! CALL gmshFltkOpenTreeItem( & & name=name_, ierr=ierr) ! - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_OpenTreeItem !---------------------------------------------------------------------------- @@ -404,18 +395,17 @@ END FUNCTION Fltk_OpenTreeItem ! GMSH_API void gmshFltkCloseTreeItem(const char *name, ! int *ierr); -FUNCTION Fltk_CloseTreeItem(name) & - & RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: name +FUNCTION Fltk_CloseTreeItem(name) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans ! internal - CHARACTER(LEN=maxStrLen) :: name_ + CHARACTER(maxStrLen) :: name_ ! name_ = gmsh_CString(name) ! CALL gmshFltkCloseTreeItem(name=name_, ierr=ierr) ! - ans = int(ierr, i4b) + ans = INT(ierr, i4b) END FUNCTION Fltk_CloseTreeItem !---------------------------------------------------------------------------- diff --git a/src/modules/GmshAPI/src/GmshGraphics_Class.F90 b/src/modules/GmshAPI/src/GmshGraphics_Class.F90 index 202e1d87a..caf744ba2 100644 --- a/src/modules/GmshAPI/src/GmshGraphics_Class.F90 +++ b/src/modules/GmshAPI/src/GmshGraphics_Class.F90 @@ -15,7 +15,6 @@ ! along with this program. If not, see ! -#ifdef USE_GMSH_SDK MODULE GmshGraphics_Class USE GlobalData, ONLY: DFP, I4B, LGT USE GmshInterface @@ -79,4 +78,3 @@ FUNCTION graphics_Draw(obj) RESULT( ans ) END FUNCTION graphics_Draw END MODULE GmshGraphics_Class -#endif \ No newline at end of file diff --git a/src/modules/GmshAPI/src/GmshInterface/GmshInterface.F90 b/src/modules/GmshAPI/src/GmshInterface/GmshInterface.F90 index 5bc173cbb..d5fa8f45e 100644 --- a/src/modules/GmshAPI/src/GmshInterface/GmshInterface.F90 +++ b/src/modules/GmshAPI/src/GmshInterface/GmshInterface.F90 @@ -40,7 +40,7 @@ MODULE GmshInterface INTEGER, PARAMETER, PUBLIC :: GMSH_API_VERSION_MINOR = 11 INTEGER, PARAMETER, PUBLIC :: GMSH_API_VERSION_PATCH = 0 INTEGER, PARAMETER, PUBLIC :: GMSH_API_MAX_STR_LEN = maxStrLen -CHARACTER(LEN=100), PARAMETER, PUBLIC :: GMSH_API_VERSION = "4.11.0" +CHARACTER(100), PARAMETER, PUBLIC :: GMSH_API_VERSION = "4.11.0" #include "./Gmsh.inc" #include "./GmshOption.inc" diff --git a/src/modules/GmshAPI/src/GmshInterface/GmshModelGeoMesh.inc b/src/modules/GmshAPI/src/GmshInterface/GmshModelGeoMesh.inc index 4e258f3d6..5f8577299 100644 --- a/src/modules/GmshAPI/src/GmshInterface/GmshModelGeoMesh.inc +++ b/src/modules/GmshAPI/src/GmshInterface/GmshModelGeoMesh.inc @@ -28,14 +28,14 @@ ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetSize(dimTags, dimTags_n, size, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetSize") - IMPORT - _ST_V_IN_ :: dimTags_n - _I_IN_ :: dimTags( dimTags_n ) - _R_V_IN_ :: size - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetSize + SUBROUTINE gmshModelGeoMeshSetSize(dimTags, dimTags_n, size, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetSize") + IMPORT + _ST_V_IN_ :: dimTags_n + _I_IN_ :: dimTags(dimTags_n) + _R_V_IN_ :: size + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetSize END INTERFACE PUBLIC :: gmshModelGeoMeshSetSize @@ -57,15 +57,15 @@ PUBLIC :: gmshModelGeoMeshSetSize ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetTransfiniteCurve(tag, nPoints, & - & meshType, coef, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetTransfiniteCurve") - IMPORT - _I_V_IN_ :: tag, nPoints - _CPTR_V_IN_ :: meshType - _R_V_IN_ :: coef - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetTransfiniteCurve + SUBROUTINE gmshModelGeoMeshSetTransfiniteCurve(tag, nPoints, & + & meshType, coef, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetTransfiniteCurve") + IMPORT + _I_V_IN_ :: tag, nPoints + _CPTR_V_IN_ :: meshType + _R_V_IN_ :: coef + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetTransfiniteCurve END INTERFACE PUBLIC :: gmshModelGeoMeshSetTransfiniteCurve @@ -88,16 +88,16 @@ PUBLIC :: gmshModelGeoMeshSetTransfiniteCurve ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetTransfiniteSurface(tag, arrangement, & - & cornerTags, cornerTags_n, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetTransfiniteSurface") - IMPORT - _I_V_IN_ :: tag - _CPTR_V_IN_ :: arrangement - _ST_V_IN_ :: cornerTags_n - _I_IN_ :: cornerTags(cornerTags_n) - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetTransfiniteSurface + SUBROUTINE gmshModelGeoMeshSetTransfiniteSurface(tag, arrangement, & + & cornerTags, cornerTags_n, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetTransfiniteSurface") + IMPORT + _I_V_IN_ :: tag + _CPTR_V_IN_ :: arrangement + _ST_V_IN_ :: cornerTags_n + _I_IN_ :: cornerTags(cornerTags_n) + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetTransfiniteSurface END INTERFACE PUBLIC :: gmshModelGeoMeshSetTransfiniteSurface @@ -115,15 +115,15 @@ PUBLIC :: gmshModelGeoMeshSetTransfiniteSurface ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetTransfiniteVolume(tag, cornerTags, & - & cornerTags_n, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetTransfiniteVolume") - IMPORT - _I_V_IN_ :: tag - _ST_V_IN_ :: cornerTags_n - _I_IN_ :: cornerTags(cornerTags_n) - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetTransfiniteVolume + SUBROUTINE gmshModelGeoMeshSetTransfiniteVolume(tag, cornerTags, & + & cornerTags_n, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetTransfiniteVolume") + IMPORT + _I_V_IN_ :: tag + _ST_V_IN_ :: cornerTags_n + _I_IN_ :: cornerTags(cornerTags_n) + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetTransfiniteVolume END INTERFACE PUBLIC :: gmshModelGeoMeshSetTransfiniteVolume @@ -132,6 +132,29 @@ PUBLIC :: gmshModelGeoMeshSetTransfiniteVolume ! !---------------------------------------------------------------------------- +!> Set a recombination meshing constraint on the entity of dimension `dim' and + !! tag `tag' in the built-in CAD kernel representation. Currently only + !! entities of dimension 2 (to recombine triangles into quadrangles) are + !! supported; `angle' specifies the threshold angle for the simple + !! recombination algorithm. + +INTERFACE + SUBROUTINE gmshModelGeoMeshSetRecombine(dim, tag, angle, ierr) & + BIND(C, NAME="gmshModelGeoMeshSetRecombine") + IMPORT + _I_V_IN_ :: dim + _I_V_IN_ :: tag + _R_V_IN_ :: angle + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetRecombine +END INTERFACE + +PUBLIC :: gmshModelGeoMeshSetRecombine + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + ! Set a smoothing meshing constraint on the entity of dimension `dim' and tag ! `tag' in the built-in CAD kernel representation. `val' iterations of a ! Laplace smoother are applied. @@ -142,12 +165,12 @@ PUBLIC :: gmshModelGeoMeshSetTransfiniteVolume ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetSmoothing(dim, tag, val, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetSmoothing") - IMPORT - _I_V_IN_ :: dim, tag, val - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetSmoothing + SUBROUTINE gmshModelGeoMeshSetSmoothing(dim, tag, val, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetSmoothing") + IMPORT + _I_V_IN_ :: dim, tag, val + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetSmoothing END INTERFACE PUBLIC :: gmshModelGeoMeshSetSmoothing @@ -168,12 +191,12 @@ PUBLIC :: gmshModelGeoMeshSetSmoothing ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetReverse(dim, tag, val, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetReverse") - IMPORT - _I_V_IN_ :: dim, tag, val - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetReverse + SUBROUTINE gmshModelGeoMeshSetReverse(dim, tag, val, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetReverse") + IMPORT + _I_V_IN_ :: dim, tag, val + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetReverse END INTERFACE PUBLIC :: gmshModelGeoMeshSetReverse @@ -188,12 +211,12 @@ PUBLIC :: gmshModelGeoMeshSetReverse ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetAlgorithm(dim, tag, val, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetAlgorithm") - IMPORT - _I_V_IN_ :: dim, tag, val - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetAlgorithm + SUBROUTINE gmshModelGeoMeshSetAlgorithm(dim, tag, val, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetAlgorithm") + IMPORT + _I_V_IN_ :: dim, tag, val + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetAlgorithm END INTERFACE PUBLIC :: gmshModelGeoMeshSetAlgorithm @@ -208,12 +231,12 @@ PUBLIC :: gmshModelGeoMeshSetAlgorithm ! int *ierr); INTERFACE -SUBROUTINE gmshModelGeoMeshSetSizeFromBoundary(dim, tag, val, ierr) & - & BIND(C, NAME="gmshModelGeoMeshSetSizeFromBoundary") - IMPORT - _I_V_IN_ :: dim, tag, val - _I_OUT_ :: ierr -END SUBROUTINE gmshModelGeoMeshSetSizeFromBoundary + SUBROUTINE gmshModelGeoMeshSetSizeFromBoundary(dim, tag, val, ierr) & + & BIND(C, NAME="gmshModelGeoMeshSetSizeFromBoundary") + IMPORT + _I_V_IN_ :: dim, tag, val + _I_OUT_ :: ierr + END SUBROUTINE gmshModelGeoMeshSetSizeFromBoundary END INTERFACE -PUBLIC :: gmshModelGeoMeshSetSizeFromBoundary \ No newline at end of file +PUBLIC :: gmshModelGeoMeshSetSizeFromBoundary diff --git a/src/modules/GmshAPI/src/GmshModelGeoMesh_Class.F90 b/src/modules/GmshAPI/src/GmshModelGeoMesh_Class.F90 index d8c1b4215..83546a1ef 100644 --- a/src/modules/GmshAPI/src/GmshModelGeoMesh_Class.F90 +++ b/src/modules/GmshAPI/src/GmshModelGeoMesh_Class.F90 @@ -15,50 +15,62 @@ ! along with this program. If not, see ! -#ifdef USE_GMSH_SDK MODULE GmshModelGeoMesh_Class USE GlobalData, ONLY: DFP, I4B, LGT -USE Utility, ONLY: Reallocate +USE Utility, ONLY: Reallocate, input USE GmshInterface USE CInterface, ONLY: C_PTR_TO_INT_VEC USE ISO_C_BINDING IMPLICIT NONE PRIVATE -CHARACTER( LEN = * ), PARAMETER :: modName = "GMSHMODELGEOMESH_CLASS" -INTEGER( C_INT ) :: ierr +CHARACTER(*), PARAMETER :: modName = "GmshModelGeoMesh_Class" +INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) -INTEGER( I4B ), PARAMETER :: maxStrLen = 256 +INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: GmshModelGeoMesh_ +PUBLIC :: GmshModelGeoMeshPointer_ !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- TYPE :: GmshModelGeoMesh_ - CONTAINS +CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS( Obj ) :: SetSize => mesh_SetSize - PROCEDURE, PUBLIC, PASS( Obj ) :: SetTransfiniteCurve => mesh_SetTransfiniteCurve - PROCEDURE, PUBLIC, PASS( Obj ) :: SetTransfiniteSurface => mesh_SetTransfiniteSurface - PROCEDURE, PUBLIC, PASS( Obj ) :: SetTransfiniteVolume => mesh_SetTransfiniteVolume - PROCEDURE, PUBLIC, PASS( Obj ) :: SetSmoothing => mesh_SetSmoothing - PROCEDURE, PUBLIC, PASS( Obj ) :: SetReverse => mesh_SetReverse - PROCEDURE, PUBLIC, PASS( Obj ) :: SetAlgorithm => mesh_SetAlgorithm - PROCEDURE, PUBLIC, PASS( Obj ) :: SetSizeFromBoundary => mesh_SetSizeFromBoundary + PROCEDURE, PUBLIC, NOPASS :: SetSize => mesh_SetSize + PROCEDURE, PUBLIC, NOPASS :: SetTransfiniteCurve & + & => mesh_SetTransfiniteCurve + PROCEDURE, PUBLIC, NOPASS :: SetTransfiniteSurface & + & => mesh_SetTransfiniteSurface + PROCEDURE, PUBLIC, NOPASS :: SetTransfiniteVolume => & + & mesh_SetTransfiniteVolume + PROCEDURE, PUBLIC, NOPASS :: SetRecombine => & + & mesh_SetRecombine + PROCEDURE, PUBLIC, NOPASS :: SetSmoothing => & + & mesh_SetSmoothing + PROCEDURE, PUBLIC, NOPASS :: SetReverse => & + & mesh_SetReverse + PROCEDURE, PUBLIC, NOPASS :: SetAlgorithm => & + & mesh_SetAlgorithm + PROCEDURE, PUBLIC, NOPASS :: SetSizeFromBoundary => & + & mesh_SetSizeFromBoundary END TYPE GmshModelGeoMesh_ -PUBLIC :: GmshModelGeoMesh_ -TYPE( GmshModelGeoMesh_ ), PUBLIC, PARAMETER :: TypeGmshModelGeoMesh = GmshModelGeoMesh_() +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE( GmshModelGeoMesh_ ), PUBLIC, PARAMETER :: TypeGmshModelGeoMesh & + & = GmshModelGeoMesh_() !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- TYPE :: GmshModelGeoMeshPointer_ - CLASS( GmshModelGeoMesh_ ), POINTER :: Ptr => NULL() + CLASS(GmshModelGeoMesh_), POINTER :: Ptr => NULL() END TYPE -PUBLIC :: GmshModelGeoMeshPointer_ - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -69,120 +81,236 @@ MODULE GmshModelGeoMesh_Class ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetSize(obj, dimTags, Meshsize) & - & RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: dimTags( : ) - REAL( DFP ), INTENT( IN ) :: Meshsize - INTEGER( I4B ) :: ans - CALL gmshModelGeoMeshSetSize( dimTags, & - & SIZE(dimTags, KIND=C_SIZE_T), Meshsize, ierr ) - ans = int( ierr, i4b ) +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Set size +! +!# Introduction +! +! Set a mesh size constraint on the entities `dimTags' in the built-in CAD +! kernel representation. Currently only entities of dimension 0 (points) are +! handled. + +FUNCTION mesh_SetSize(dimTags, Meshsize) & + & RESULT(ans) + INTEGER(I4B), INTENT(IN) :: dimTags(:) + REAL(DFP), INTENT(IN) :: Meshsize + INTEGER(I4B) :: ans + CALL gmshModelGeoMeshSetSize(dimTags, & + & SIZE(dimTags, KIND=C_SIZE_T), Meshsize, ierr) + ans = INT(ierr, i4b) END FUNCTION mesh_SetSize !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetTransfiniteCurve(obj, tag, nPoints, meshType, & - & coef ) RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: tag, nPoints - CHARACTER( LEN = * ), INTENT( IN ) :: meshType - REAL( DFP ), INTENT( IN ) :: coef - INTEGER( I4B ) :: ans - ! - CHARACTER( LEN = maxStrLen ), TARGET :: meshType_ - meshType_ = TRIM( meshType ) // C_NULL_CHAR +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Set transfinite curve +! +!# Introduction +! +! Set a transfinite meshing constraint on the curve `tag' in the built-in CAD +! kernel representation, with `numNodes' nodes distributed according to +! `meshType' and `coef'. Currently supported types are "Progression" +! (geometrical progression with power `coef') and "Bump" (refinement toward +! both extremities of the curve). + +FUNCTION mesh_SetTransfiniteCurve(tag, nPoints, meshType, coef & + & ) RESULT(ans) + INTEGER(I4B), INTENT(IN) :: tag, nPoints + CHARACTER(*), OPTIONAL, INTENT(IN) :: meshType + !! Default value is "Progression" + REAL(DFP), OPTIONAL, INTENT(IN) :: coef + !! Default value is 1.0_DFP + INTEGER(I4B) :: ans + + ! internal variables + CHARACTER(maxStrLen), TARGET :: meshType_ + + IF (PRESENT(meshType)) THEN + meshType_ = TRIM(meshType)//C_NULL_CHAR + ELSE + meshType_ = "Progression"//C_NULL_CHAR + END IF CALL gmshModelGeoMeshSetTransfiniteCurve(tag, nPoints, & - & C_LOC(meshType_), coef, ierr ) - ans = int( ierr, i4b ) + & C_LOC(meshType_), input(option=coef, default=1.0_DFP), ierr) + ans = INT(ierr, i4b) END FUNCTION mesh_SetTransfiniteCurve !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetTransfiniteSurface(obj, tag, arrangement, & - & cornerTags ) RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: tag - CHARACTER( LEN = * ), INTENT( IN ) :: arrangement - INTEGER( I4B ), INTENT( IN ) :: cornerTags(:) - INTEGER( I4B ) :: ans - ! - CHARACTER( LEN = maxStrLen ), TARGET :: arrangement_ - arrangement_ = TRIM( arrangement ) // C_NULL_CHAR +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Set transfinite surface +! +!# Introduction +! +! Set a transfinite meshing constraint on the surface `tag' in the built-in +! CAD kernel representation. `arrangement' describes the arrangement of the +! triangles when the surface is not flagged as recombined: currently +! supported values are "Left", "Right", "AlternateLeft" and "AlternateRight". +! `cornerTags' can be used to specify the (3 or 4) corners of the transfinite +! interpolation explicitly; specifying the corners explicitly is mandatory if +! the surface has more that 3 or 4 points on its boundary. + +FUNCTION mesh_SetTransfiniteSurface(tag, arrangement, & + & cornerTags) RESULT(ans) + INTEGER(I4B), INTENT(IN) :: tag + CHARACTER(*), OPTIONAL, INTENT(IN) :: arrangement + INTEGER(I4B), OPTIONAL, INTENT(IN) :: cornerTags(:) + INTEGER(I4B) :: ans + ! internal variables + CHARACTER(maxStrLen), TARGET :: arrangement_ + INTEGER(C_SIZE_T) :: cornerTags_n + INTEGER(I4B), ALLOCATABLE :: cornerTags_(:) + + IF (PRESENT(arrangement)) THEN + arrangement_ = TRIM(arrangement)//C_NULL_CHAR + ELSE + arrangement_ = "Left"//C_NULL_CHAR + END IF + + IF (PRESENT(cornerTags)) THEN + cornerTags_n = SIZE(cornerTags) + cornerTags_ = cornerTags + ELSE + cornerTags_n = 0_I4B + ALLOCATE (cornerTags_(0)) + END IF + CALL gmshModelGeoMeshSetTransfiniteSurface(tag, & - & C_LOC(arrangement_), cornerTags, & - & SIZE(cornerTags, KIND=C_SIZE_T), ierr) - ans = int( ierr, i4b ) + & C_LOC(arrangement_), cornerTags_, & + & cornerTags_n, ierr) + + IF (ALLOCATED(cornerTags_)) DEALLOCATE (cornerTags_) + + ans = INT(ierr, i4b) END FUNCTION mesh_SetTransfiniteSurface !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetTransfiniteVolume(obj, tag, cornerTags) & - & RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: tag - INTEGER( I4B ), INTENT( IN ) :: cornerTags( : ) - INTEGER( I4B ) :: ans - CALL gmshModelGeoMeshSetTransfiniteVolume(tag, cornerTags, & - & SIZE(cornerTags, KIND=C_SIZE_T), ierr) - ans = int(ierr, i4b) +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Set transfinite volume +! +!# Introduction +! +! Set a transfinite meshing constraint on the surface `tag' in the built-in +! CAD kernel representation. `cornerTags' can be used to specify the (6 or 8) +! corners of the transfinite interpolation explicitly. */ + +FUNCTION mesh_SetTransfiniteVolume(tag, cornerTags) & + & RESULT(ans) + INTEGER(I4B), INTENT(IN) :: tag + INTEGER(I4B), OPTIONAL, INTENT(IN) :: cornerTags(:) + INTEGER(I4B) :: ans + ! + INTEGER(C_SIZE_T) :: cornerTags_n + INTEGER(I4B), ALLOCATABLE :: cornerTags_(:) + + IF (PRESENT(cornerTags)) THEN + cornerTags_n = SIZE(cornerTags) + cornerTags_ = cornerTags + ELSE + cornerTags_n = 0_I4B + ALLOCATE (cornerTags_(0)) + END IF + + CALL gmshModelGeoMeshSetTransfiniteVolume(tag, cornerTags_, & + & cornerTags_n, ierr) + + IF (ALLOCATED(cornerTags_)) DEALLOCATE (cornerTags_) + ans = INT(ierr, i4b) END FUNCTION mesh_SetTransfiniteVolume !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetSmoothing(obj, dim, tag, val) & - & RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: dim, tag, val - INTEGER( I4B ) :: ans +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Recombine mesh +! +!# Introduction +! +! Set a recombination meshing constraint on the entity of dimension `dim' and +! tag `tag' in the built-in CAD kernel representation. Currently only +! entities of dimension 2 (to recombine triangles into quadrangles) are +! supported; `angle' specifies the threshold angle for the simple +! recombination algorithm. + +FUNCTION mesh_SetRecombine(dim, tag, angle) & + & RESULT(ans) + INTEGER(I4B), INTENT(IN) :: dim, tag + REAL(DFP), OPTIONAL, INTENT(IN) :: angle + INTEGER(I4B) :: ans + + CALL gmshModelGeoMeshSetRecombine(dim, tag, & + & input(option=angle, default=45.0_DFP), ierr) + + ans = INT(ierr, i4b) +END FUNCTION mesh_SetRecombine + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Set SetSmoothing +! +!# Introduction +! +! Set a smoothing meshing constraint on the entity of dimension `dim' and tag +! `tag' in the built-in CAD kernel representation. `val' iterations of a +! Laplace smoother are applied. + +FUNCTION mesh_SetSmoothing(dim, tag, val) & + & RESULT(ans) + INTEGER(I4B), INTENT(IN) :: dim, tag, val + INTEGER(I4B) :: ans CALL gmshModelGeoMeshSetSmoothing(dim, tag, val, ierr) - ans = int( ierr, i4b ) + ans = INT(ierr, i4b) END FUNCTION mesh_SetSmoothing !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetReverse(obj, dim, tag, val) RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: dim, tag, val - INTEGER( I4B ) :: ans +FUNCTION mesh_SetReverse(dim, tag, val) RESULT(ans) + INTEGER(I4B), INTENT(IN) :: dim, tag, val + INTEGER(I4B) :: ans CALL gmshModelGeoMeshSetReverse(dim, tag, val, ierr) - ans = int( ierr, i4b ) + ans = INT(ierr, i4b) END FUNCTION mesh_SetReverse !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetAlgorithm(obj, dim, tag, val) RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: dim, tag, val - INTEGER( I4B ) :: ans +FUNCTION mesh_SetAlgorithm(dim, tag, val) RESULT(ans) + INTEGER(I4B), INTENT(IN) :: dim, tag, val + INTEGER(I4B) :: ans CALL gmshModelGeoMeshSetAlgorithm(dim, tag, val, ierr) - ans = int( ierr, i4b ) + ans = INT(ierr, i4b) END FUNCTION mesh_SetAlgorithm !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION mesh_SetSizeFromBoundary(obj, dim, tag, val) & - & RESULT( ans ) - CLASS( GmshModelGeoMesh_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: dim, tag, val - INTEGER( I4B ) :: ans +FUNCTION mesh_SetSizeFromBoundary(dim, tag, val) & + & RESULT(ans) + INTEGER(I4B), INTENT(IN) :: dim, tag, val + INTEGER(I4B) :: ans CALL gmshModelGeoMeshSetSizeFromBoundary(dim, tag, val, ierr) - ans = int( ierr, i4b ) + ans = INT(ierr, i4b) END FUNCTION mesh_SetSizeFromBoundary END MODULE GmshModelGeoMesh_Class -#endif \ No newline at end of file diff --git a/src/modules/GmshAPI/src/GmshModelGeo_Class.F90 b/src/modules/GmshAPI/src/GmshModelGeo_Class.F90 index 395fd13b7..5c0b3f1d6 100644 --- a/src/modules/GmshAPI/src/GmshModelGeo_Class.F90 +++ b/src/modules/GmshAPI/src/GmshModelGeo_Class.F90 @@ -26,7 +26,7 @@ MODULE GmshModelGeo_Class USE ISO_C_BINDING IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "GMSHOPTION_CLASS" +CHARACTER(*), PARAMETER :: modName = "GMSHOPTION_CLASS" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(C_INT) :: cintvar @@ -38,8 +38,6 @@ MODULE GmshModelGeo_Class ! !---------------------------------------------------------------------------- -#define _DT_ GmshModelGeo_ - TYPE :: GmshModelGeo_ TYPE(GmshModelGeoMesh_), POINTER :: mesh => NULL() CONTAINS @@ -113,7 +111,7 @@ MODULE GmshModelGeo_Class SUBROUTINE geo_Initiate(obj) CLASS(GmshModelGeo_), INTENT(INOUT) :: obj !> internal var - CHARACTER(LEN=*), PARAMETER :: myName = "geo_Initiate" + CHARACTER(*), PARAMETER :: myName = "geo_Initiate" !> main program IF (ASSOCIATED(obj%Mesh)) THEN CALL e%raiseError(modName//"::"//myName//" - "// & @@ -143,10 +141,10 @@ FUNCTION geo_AddPoint(x, y, z, meshSize, tag) RESULT(ans) & y=gmsh_cdouble(y), & & z=gmsh_cdouble(z), & & meshSize=gmsh_cdouble(meshSize), & - & tag=gmsh_cint(INPUT(default=-1, option=tag)), & + & tag=gmsh_cint(INPUT(default=-1_I4B, option=tag)), & & ierr=ierr) ! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) ! END FUNCTION geo_AddPoint @@ -170,7 +168,7 @@ FUNCTION geo_AddLine(startTag, endTag, tag) RESULT(ans) & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) ! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddLine !---------------------------------------------------------------------------- @@ -201,7 +199,7 @@ FUNCTION geo_AddCircleArc(startTag, centerTag, endTag, tag, nx, ny, & & nz=gmsh_opt_cdouble(0.0_DFP, nz), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! END FUNCTION geo_AddCircleArc @@ -234,7 +232,7 @@ FUNCTION geo_AddEllipseArc(startTag, centerTag, majorTag, endTag, & & nz=gmsh_cdouble(nz), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! END FUNCTION geo_AddEllipseArc @@ -260,7 +258,7 @@ FUNCTION geo_AddSpline(pointTags, tag) & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddSpline !---------------------------------------------------------------------------- @@ -285,7 +283,7 @@ FUNCTION geo_AddBSpline(pointTags, tag) & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! END FUNCTION geo_AddBSpline @@ -309,7 +307,7 @@ FUNCTION geo_AddBezier(pointTags, tag) & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! END FUNCTION geo_AddBezier @@ -334,7 +332,7 @@ FUNCTION geo_AddPolyline(pointTags, tag) & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddPolyline !---------------------------------------------------------------------------- @@ -360,7 +358,7 @@ FUNCTION geo_AddCompoundSpline(curveTags, & & numIntervals=gmsh_cint(numIntervals), & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddCompoundSpline !---------------------------------------------------------------------------- @@ -387,7 +385,7 @@ FUNCTION geo_AddCompoundBSpline(curveTags, & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddCompoundBSpline !---------------------------------------------------------------------------- @@ -413,10 +411,10 @@ FUNCTION geo_AddCurveLoop(curveTags, tag, reorient) & & curveTags=gmsh_cint(curveTags), & & curveTags_n=INT(SIZE(curveTags), C_SIZE_T), & & tag=gmsh_cint(INPUT(default=-1, option=tag)), & - & reorient=optval_c_bool(.false., reorient), & + & reorient=optval_c_bool(.FALSE., reorient), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddCurveLoop !---------------------------------------------------------------------------- @@ -470,7 +468,7 @@ FUNCTION geo_AddPlaneSurface(wireTags, tag) & & tag=gmsh_cint(input(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddPlaneSurface !---------------------------------------------------------------------------- @@ -497,7 +495,7 @@ FUNCTION geo_AddSurfaceFilling(wireTags, tag, & & sphereCenterTag=gmsh_cint(sphereCenterTag), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! END FUNCTION geo_AddSurfaceFilling @@ -514,15 +512,14 @@ FUNCTION geo_AddSurfaceLoop(surfaceTags, tag) & INTEGER(I4B), INTENT(IN) :: surfaceTags(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: tag INTEGER(I4B) :: ans - ! + cintvar = gmshModelGeoAddSurfaceLoop( & & surfaceTags=gmsh_cint(surfaceTags), & & surfaceTags_n=INT(SIZE(surfaceTags), C_SIZE_T), & & tag=gmsh_cint(input(default=-1, option=tag)), & & ierr=ierr) - !! - ans = int(cintvar, i4b) - !! + + ans = INT(cintvar, i4b) END FUNCTION geo_AddsurfaceLoop !---------------------------------------------------------------------------- @@ -547,7 +544,7 @@ FUNCTION geo_AddVolume(shellTags, tag) & & tag=gmsh_cint(input(default=-1, option=tag)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! END FUNCTION geo_AddVolume @@ -563,39 +560,39 @@ END FUNCTION geo_AddVolume !! geometry explicitly; otherwise a new tag is selected automatically. Return !! the tag of the geometry. -function geo_AddGeometry(geometry, numbers, & - & strings, tag) result(ans) +FUNCTION geo_AddGeometry(geometry, numbers, & + & strings, tag) RESULT(ans) !! - character(len=*), intent(in) :: geometry - class(*), intent(in), optional :: numbers(:) - character(len=*), intent(in), optional :: strings(:) - integer(i4b), intent(in), optional :: tag - integer(i4b) :: ans + CHARACTER(*), INTENT(in) :: geometry + CLASS(*), INTENT(in), OPTIONAL :: numbers(:) + CHARACTER(*), INTENT(in), OPTIONAL :: strings(:) + INTEGER(i4b), INTENT(in), OPTIONAL :: tag + INTEGER(i4b) :: ans !! - character(len=maxStrLen, kind=c_char), allocatable :: strings_strs(:) - type(c_ptr), allocatable :: strings_(:) - real(c_double), allocatable :: numbers0(:) + CHARACTER(maxStrLen, kind=C_CHAR), ALLOCATABLE :: strings_strs(:) + TYPE(C_PTR), ALLOCATABLE :: strings_(:) + REAL(C_DOUBLE), ALLOCATABLE :: numbers0(:) !! - call gmsh_GetCharArray_cPtr(strings, strings_strs, strings_) + CALL gmsh_GetCharArray_cPtr(strings, strings_strs, strings_) ! - if (present(numbers)) then + IF (PRESENT(numbers)) THEN numbers0 = gmsh_cdouble(numbers) - else - allocate (numbers0(0)) - end if + ELSE + ALLOCATE (numbers0(0)) + END IF ! cintvar = gmshModelGeoAddGeometry( & & geometry=gmsh_CString(geometry), & & numbers=numbers0, & - & numbers_n=size(numbers0, kind=c_size_t), & + & numbers_n=SIZE(numbers0, kind=C_SIZE_T), & & strings=strings_, & & strings_n=gmsh_size_str(strings), & & tag=gmsh_cint(input(default=-1, option=tag)), & & ierr=ierr) ! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) ! -end function geo_AddGeometry +END FUNCTION geo_AddGeometry !---------------------------------------------------------------------------- ! @@ -607,15 +604,15 @@ end function geo_AddGeometry !! otherwise a new tag is selected automatically. Return the tag of the point. !! For surface geometries, only the `x' and `y' coordinates are used. -function geo_AddPointOnGeometry(geometryTag, x, y, z, meshSize, & - & tag) result(ans) - integer(i4b), intent(in) :: geometryTag - class(*), intent(in) :: x - class(*), intent(in) :: y - class(*), intent(in), optional :: z - class(*), intent(in), optional :: meshSize - integer(i4b), intent(in), optional :: tag - integer(i4b) :: ans +FUNCTION geo_AddPointOnGeometry(geometryTag, x, y, z, meshSize, & + & tag) RESULT(ans) + INTEGER(i4b), INTENT(in) :: geometryTag + CLASS(*), INTENT(in) :: x + CLASS(*), INTENT(in) :: y + CLASS(*), INTENT(in), OPTIONAL :: z + CLASS(*), INTENT(in), OPTIONAL :: meshSize + INTEGER(i4b), INTENT(in), OPTIONAL :: tag + INTEGER(i4b) :: ans !! cintvar = gmshModelGeoAddPointOnGeometry( & & geometryTag=gmsh_cint(geometryTag), & @@ -626,9 +623,9 @@ function geo_AddPointOnGeometry(geometryTag, x, y, z, meshSize, & & tag=gmsh_opt_cint(default=-1_I4B, option=tag), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) !! -end function geo_AddPointOnGeometry +END FUNCTION geo_AddPointOnGeometry !---------------------------------------------------------------------------- ! @@ -666,7 +663,7 @@ FUNCTION geo_Extrude(dimTags, dx, dy, dz, & & numElements_n=SIZE(numElements, KIND=C_SIZE_T), & & heights=gmsh_cdouble(heights), & & heights_n=SIZE(heights, KIND=C_SIZE_T), & - & recombine=optval_c_bool(.false., recombine), & + & recombine=optval_c_bool(.FALSE., recombine), & & ierr=ierr) !! outDimTags = gmsh_dimtag_c2f(cptr, outDimTags_n) @@ -730,7 +727,7 @@ FUNCTION geo_GeoRevolve(dimTags, x, y, z, ax, ay, az, & & numElements_n=SIZE(numElements0, KIND=C_SIZE_T), & & heights=heights0, & & heights_n=SIZE(heights0, KIND=C_SIZE_T), & - & recombine=optval_c_bool(.false., recombine), & + & recombine=optval_c_bool(.FALSE., recombine), & & ierr=ierr) !! outDimTags = gmsh_dimtag_c2f(cptr, outDimTags_n) @@ -800,7 +797,7 @@ FUNCTION geo_Twist(dimTags, x, y, z, dx, dy, dz, ax, & & numElements_n=SIZE(numElements0, KIND=C_SIZE_T), & & heights=heights0, & & heights_n=SIZE(heights0, KIND=C_SIZE_T), & - & recombine=optval_c_bool(.false., recombine), & + & recombine=optval_c_bool(.FALSE., recombine), & & ierr=ierr) !! outDimTags = gmsh_dimtag_c2f(cptr, outDimTags_n) @@ -852,16 +849,16 @@ FUNCTION geo_ExtrudeBoundaryLayer(dimTags, & !! CALL gmshModelGeoExtrudeBoundaryLayer( & & dimTags=gmsh_cint(dimTags), & - & dimTags_n=SIZE(dimTags, kind=c_size_t), & + & dimTags_n=SIZE(dimTags, kind=C_SIZE_T), & & outDimTags=cptr, & & outDimTags_n=outDimTags_n, & & numElements=numElements0, & - & numElements_n=SIZE(numElements0, kind=c_size_t), & + & numElements_n=SIZE(numElements0, kind=C_SIZE_T), & & heights=heights0, & - & heights_n=SIZE(heights0, kind=c_size_t), & - & recombine=optval_c_bool(.false., recombine), & - & second=optval_c_bool(.false., second), & - & viewIndex=optval_c_bool(.false., viewIndex), & + & heights_n=SIZE(heights0, kind=C_SIZE_T), & + & recombine=optval_c_bool(.FALSE., recombine), & + & second=optval_c_bool(.FALSE., second), & + & viewIndex=optval_c_bool(.FALSE., viewIndex), & & ierr=ierr) !! outDimTags = gmsh_dimtag_c2f(cptr, outDimTags_n) @@ -1038,15 +1035,15 @@ END FUNCTION geo_Copy !! of higher-dimensional entities. If `recursive' is true, remove all the !! entities on their boundaries, down to dimension 0. -FUNCTION geo_Remove(dimTags, recursive) RESULT(ans) +FUNCTION geo_Remove(dimTags, RECURSIVE) RESULT(ans) INTEGER(I4B), INTENT(IN) :: dimTags(:, :) - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: recursive + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: RECURSIVE INTEGER(I4B) :: ans !! CALL gmshModelGeoRemove( & & dimTags=dimTags, & & dimTags_n=SIZE(dimTags, KIND=C_SIZE_T), & - & recursive=optval_c_bool(.false., recursive), & + & RECURSIVE=optval_c_bool(.FALSE., RECURSIVE), & & ierr=ierr) !! ans = INT(ierr, I4B) @@ -1084,7 +1081,7 @@ FUNCTION geo_SplitCurve(tag, pointTags) & CALL gmshModelGeoSplitCurve( & & tag=gmsh_cint(tag), & & pointTags=gmsh_cint(pointTags), & - & pointTags_n=size(pointTags, kind=c_size_t), & + & pointTags_n=SIZE(pointTags, kind=C_SIZE_T), & & curveTags=cptr, & & curveTags_n=curveTags_n, & & ierr=ierr) @@ -1104,7 +1101,7 @@ FUNCTION geo_GetMaxTag(dim) RESULT(ans) INTEGER(I4B), INTENT(IN) :: dim INTEGER(I4B) :: ans cintvar = gmshModelGeoGetMaxTag(dim=gmsh_cint(dim), ierr=ierr) - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_GetMaxTag !---------------------------------------------------------------------------- @@ -1136,18 +1133,18 @@ FUNCTION geo_AddPhysicalGroup(dim, tags, tag, name) & INTEGER(I4B), INTENT(IN) :: dim INTEGER(I4B), INTENT(IN) :: tags(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: tag - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: name + CHARACTER(*), OPTIONAL, INTENT(IN) :: name INTEGER(I4B) :: ans !! cintvar = gmshModelGeoAddPhysicalGroup( & & dim=gmsh_cint(dim), & & tags=gmsh_cint(tags), & - & tags_n=size(tags, kind=c_size_t), & + & tags_n=SIZE(tags, kind=C_SIZE_T), & & tag=gmsh_opt_cint(default=-1_I4B, option=tag), & & name=gmsh_CString(input(default="", option=name)), & & ierr=ierr) !! - ans = int(cintvar, i4b) + ans = INT(cintvar, i4b) END FUNCTION geo_AddPhysicalGroup !---------------------------------------------------------------------------- @@ -1174,7 +1171,7 @@ FUNCTION geo_RemovePhysicalGroups(dimTags) & !! CALL gmshModelGeoRemovePhysicalGroups( & & dimTags=dimTags0, & - & dimTags_n=SIZE(dimTags0, KIND=c_size_t), & + & dimTags_n=SIZE(dimTags0, KIND=C_SIZE_T), & & ierr=ierr) !! ans = INT(ierr, I4B) @@ -1198,7 +1195,3 @@ FUNCTION geo_Synchronize() RESULT(ans) END FUNCTION geo_Synchronize END MODULE GmshModelGeo_Class - -#ifdef _DT_ -#undef _DT_ -#endif \ No newline at end of file diff --git a/src/modules/GmshAPI/src/GmshModelMesh_Class.F90 b/src/modules/GmshAPI/src/GmshModelMesh_Class.F90 index b64ef8375..9eb60c25f 100644 --- a/src/modules/GmshAPI/src/GmshModelMesh_Class.F90 +++ b/src/modules/GmshAPI/src/GmshModelMesh_Class.F90 @@ -23,7 +23,7 @@ MODULE GmshModelMesh_Class USE ISO_C_BINDING IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "GMSHMODELMESH_CLASS" +CHARACTER(*), PARAMETER :: modName = "GmshModelMesh_Class" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(I4B), PARAMETER :: maxStrLen = 256 @@ -117,12 +117,12 @@ END FUNCTION mesh_Unpartition FUNCTION mesh_Optimize(obj, method, force, niter, dimTags) & & RESULT(ans) CLASS(GmshModelMesh_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: method + CHARACTER(*), INTENT(IN) :: method INTEGER(I4B), INTENT(IN) :: force, niter INTEGER(I4B), INTENT(IN) :: dimTags(:) INTEGER(I4B) :: ans ! - CHARACTER(LEN=maxStrLen), TARGET :: method_ + CHARACTER(maxStrLen), TARGET :: method_ method_ = TRIM(method)//C_NULL_CHAR CALL gmshModelMeshOptimize(C_LOC(method_), force, niter, & & dimTags, SIZE(dimTags, KIND=C_SIZE_T), ierr) diff --git a/src/modules/GmshAPI/src/GmshModel_Class.F90 b/src/modules/GmshAPI/src/GmshModel_Class.F90 index 20c45b990..1b3390177 100644 --- a/src/modules/GmshAPI/src/GmshModel_Class.F90 +++ b/src/modules/GmshAPI/src/GmshModel_Class.F90 @@ -29,7 +29,7 @@ MODULE GmshModel_Class USE GmshModelMesh_Class IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "GmshModel_Class" +CHARACTER(*), PARAMETER :: modName = "GmshModel_Class" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(I4B), PARAMETER :: maxStrLen = GMSH_API_MAX_STR_LEN @@ -151,7 +151,7 @@ SUBROUTINE model_initiate(obj) !! !! internal var !! - CHARACTER(LEN=*), PARAMETER :: myName = "model_initiate" + CHARACTER(*), PARAMETER :: myName = "model_initiate" !! !! main program !! @@ -183,10 +183,10 @@ END SUBROUTINE model_initiate !---------------------------------------------------------------------------- FUNCTION model_add(name) RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans ! Internal variables - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ ! name_ = gmsh_CString(name) CALL gmshModelAdd(name=C_LOC(name_), ierr=ierr) @@ -215,10 +215,10 @@ FUNCTION model_list(names) RESULT(ans) !! !! internal variables !! - CHARACTER(LEN=*), PARAMETER :: myName = "model_list()" + CHARACTER(*), PARAMETER :: myName = "model_list()" TYPE(C_PTR) :: names_ INTEGER(C_SIZE_T) :: names_n_ - CHARACTER(LEN=maxStrLen), ALLOCATABLE :: names0(:) + CHARACTER(maxStrLen), ALLOCATABLE :: names0(:) INTEGER(I4B) :: ii !! CALL gmshModelList( & @@ -247,7 +247,7 @@ END FUNCTION model_list !---------------------------------------------------------------------------- FUNCTION model_GetCurrent(name) RESULT(ans) - CHARACTER(LEN=*), INTENT(OUT) :: name + CHARACTER(*), INTENT(OUT) :: name INTEGER(I4B) :: ans ! Internal variables TYPE(C_PTR) :: cstring @@ -261,10 +261,10 @@ END FUNCTION model_GetCurrent !---------------------------------------------------------------------------- FUNCTION model_SetCurrent(name) RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans !! Internal variables - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ !! name_ = TRIM(name)//C_NULL_CHAR CALL gmshModelSetCurrent(name=C_LOC(name_), ierr=ierr) @@ -276,7 +276,7 @@ END FUNCTION model_SetCurrent !---------------------------------------------------------------------------- FUNCTION model_GetFileName(fileName) RESULT(ans) - CHARACTER(LEN=*), INTENT(OUT) :: fileName + CHARACTER(*), INTENT(OUT) :: fileName INTEGER(I4B) :: ans ! Internal variables TYPE(C_PTR) :: cstring @@ -291,10 +291,10 @@ END FUNCTION model_GetFileName !---------------------------------------------------------------------------- FUNCTION model_SetFileName(fileName) RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: fileName + CHARACTER(*), INTENT(IN) :: fileName INTEGER(I4B) :: ans ! Internal variables - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ !! name_ = TRIM(fileName)//C_NULL_CHAR CALL gmshModelSetFileName(fileName=C_LOC(name_), ierr=ierr) @@ -356,12 +356,12 @@ END FUNCTION model_GetEntities FUNCTION model_SetEntityName(dim, tag, name) & & RESULT(ans) INTEGER(I4B), INTENT(IN) :: dim, tag - CHARACTER(LEN=*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans !! !! Internal !! - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ !! name_ = TRIM(name)//C_NULL_CHAR !! @@ -380,7 +380,7 @@ END FUNCTION model_SetEntityName FUNCTION model_GetEntityName(dim, tag, name) & & RESULT(ans) INTEGER(I4B), INTENT(IN) :: dim, tag - CHARACTER(LEN=*), INTENT(OUT) :: name + CHARACTER(*), INTENT(OUT) :: name INTEGER(I4B) :: ans !! !! Internal @@ -521,13 +521,13 @@ FUNCTION model_AddPhysicalGroup(dim, tags, & INTEGER(I4B), INTENT(IN) :: dim INTEGER(I4B), INTENT(IN) :: tags(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: tag - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: name + CHARACTER(*), OPTIONAL, INTENT(IN) :: name INTEGER(I4B) :: ans ! ! Internal ! INTEGER(C_SIZE_T) :: tags_n - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ !! name_ = TRIM(input(option="", default=name))//C_NULL_CHAR !! @@ -580,12 +580,12 @@ FUNCTION model_SetPhysicalName(dim, tag, name) & & RESULT(ans) INTEGER(I4B), INTENT(IN) :: dim, tag - CHARACTER(LEN=*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans ! ! internal ! - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ !! name_ = TRIM(name)//C_NULL_CHAR !! @@ -608,12 +608,12 @@ END FUNCTION model_SetPhysicalName FUNCTION model_RemovePhysicalName(name) & & RESULT(ans) - CHARACTER(LEN=*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans ! ! internal ! - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ !! name_ = TRIM(name)//C_NULL_CHAR !! @@ -634,23 +634,22 @@ FUNCTION model_GetPhysicalName(dim, tag, name) & & RESULT(ans) INTEGER(I4B), INTENT(IN) :: dim, tag - CHARACTER(LEN=*), INTENT(OUT) :: name + CHARACTER(*), INTENT(OUT) :: name INTEGER(I4B) :: ans - ! + ! internal - ! TYPE(C_PTR) :: cptr - !! + CALL gmshModelGetPhysicalName( & & dim=gmsh_cint(dim), & & tag=gmsh_cint(tag), & & name=cptr, & & ierr=ierr) - !! + ans = INT(ierr, i4b) - !! + CALL C2Fortran(C_STRING=cptr, F_STRING=name) - !! + END FUNCTION model_GetPhysicalName !---------------------------------------------------------------------------- diff --git a/src/modules/GmshAPI/src/GmshOnelab_Class.F90 b/src/modules/GmshAPI/src/GmshOnelab_Class.F90 index 5112f7fde..429de51b6 100644 --- a/src/modules/GmshAPI/src/GmshOnelab_Class.F90 +++ b/src/modules/GmshAPI/src/GmshOnelab_Class.F90 @@ -15,7 +15,6 @@ ! along with this program. If not, see ! -#ifdef USE_GMSH_SDK MODULE GmshOnelab_Class USE GlobalData, ONLY: DFP, I4B USE Utility, ONLY: Reallocate @@ -25,13 +24,15 @@ MODULE GmshOnelab_Class USE ISO_C_BINDING IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "GMSHONELAB_CLASS" +CHARACTER(*), PARAMETER :: modName = "GmshOnelab_Class" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: GmshOnelab_ +PUBLIC :: GmshOnelabPointer_ !---------------------------------------------------------------------------- -! GmshOnelab_ +! GmshOnelab_ !---------------------------------------------------------------------------- TYPE :: GmshOnelab_ @@ -41,11 +42,23 @@ MODULE GmshOnelab_Class PROCEDURE, PUBLIC, PASS(obj) :: Set => onelab_Set PROCEDURE, PUBLIC, PASS(obj) :: Get => onelab_Get PROCEDURE, PUBLIC, PASS(obj) :: GetNumber => onelab_GetNumber - PROCEDURE, PUBLIC, PASS(obj) :: SetString => onelab_SetString PROCEDURE, PUBLIC, PASS(obj) :: GetString => onelab_GetString + PROCEDURE, PUBLIC, PASS(obj) :: SetString => onelab_SetString + + ! TODO: + ! Following methods needs to be implemented in GmshOnelab_ + ! procedure, public, pass(obj) :: getNames => onelab_getNames + ! procedure, public, pass(obj) :: setNumber => onelab_setNumber + ! procedure, public, pass(obj) :: getChanged => onelab_getChanged + ! procedure, public, pass(obj) :: setChanged => onelab_setChanged + ! procedure, public, pass(obj) :: clear => onelab_clear + ! procedure, public, pass(obj) :: run => onelab_run + END TYPE GmshOnelab_ -PUBLIC :: GmshOnelab_ +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- TYPE(GmshOnelab_), PUBLIC, PARAMETER :: TypeGmshOnelab = GmshOnelab_() @@ -57,8 +70,6 @@ MODULE GmshOnelab_Class CLASS(GmshOnelab_), POINTER :: ptr => NULL() END TYPE GmshOnelabPointer_ -PUBLIC :: GmshOnelabPointer_ - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -69,6 +80,10 @@ MODULE GmshOnelab_Class ! !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-03 +! summary: Currently, this routine does nothing + SUBROUTINE onelab_Initiate(obj) CLASS(GmshOnelab_), INTENT(INOUT) :: obj END SUBROUTINE onelab_Initiate @@ -80,34 +95,23 @@ END SUBROUTINE onelab_Initiate !> authors: Vikas Sharma, Ph. D. ! date: 23 Sept 2021 ! summary: Set one or more parameters in the ONELAB database, encoded in `format'. -! -!# Introduction -! -! Set one or more parameters in the ONELAB database, encoded in `format'. -! -! -!### Usage -! -!```fortran -! To do -!``` -FUNCTION onelab_Set(obj, data, format) RESULT(ans) +FUNCTION onelab_Set(obj, DATA, FORMAT) RESULT(ans) CLASS(GmshOnelab_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: data - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: format + CHARACTER(*), INTENT(IN) :: DATA + CHARACTER(*), OPTIONAL, INTENT(IN) :: FORMAT INTEGER(I4B) :: ans ! internal variables - CHARACTER(LEN=:), ALLOCATABLE, TARGET :: data_, format_ + CHARACTER(:), ALLOCATABLE, TARGET :: data_, format_ TYPE(C_PTR) :: format_ptr !> main - data_ = TRIM(data)//C_NULL_CHAR - IF (PRESENT(format)) THEN - format_ = TRIM(format)//C_NULL_CHAR - format_ptr = C_LOC(format_) + data_ = TRIM(DATA)//C_NULL_CHAR + IF (PRESENT(FORMAT)) THEN + format_ = TRIM(FORMAT)//C_NULL_CHAR ELSE - format_ptr = C_NULL_PTR + format_ = "json"//C_NULL_CHAR END IF + format_ptr = C_LOC(format_) CALL gmshOnelabSet(C_LOC(data_), format_ptr, ierr) ans = INT(ierr, I4B) END FUNCTION onelab_Set @@ -119,33 +123,24 @@ END FUNCTION onelab_Set !> authors: Vikas Sharma, Ph. D. ! date: 23 Sept 2021 ! summary: Get one or more parameters from the ONELAB database. -! -!# Introduction -! -! Get all the parameters (or a single one if `name` is specified) from the -! ONELAB database, encoded in `format`. -! -!### Usage -! -!```fortran -! To do -!``` -FUNCTION onelab_Get(obj, data, name, format) RESULT(ans) +FUNCTION onelab_Get(obj, DATA, name, FORMAT) RESULT(ans) CLASS(GmshOnelab_), INTENT(INOUT) :: obj - TYPE(C_PTR), TARGET, INTENT(IN) :: data(*) - CHARACTER(LEN=*), INTENT(IN) :: name - CHARACTER(LEN=*), INTENT(IN) :: format + TYPE(C_PTR), TARGET, INTENT(IN) :: DATA(*) + CHARACTER(*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: FORMAT INTEGER(I4B) :: ans ! !> internal variables ! CHARACTER( LEN = : ), ALLOCATABLE, TARGET :: name_, format_ - CHARACTER(LEN=*), PARAMETER :: myName = "onelab_Get()" + CHARACTER(*), PARAMETER :: myName = "onelab_Get()" ! !> main ! name_ = TRIM( name ) // C_NULL_CHAR ! format_ = TRIM( format ) // C_NULL_CHAR ! CALL gmshOnelabGet( data, C_LOC( name_ ), C_LOC( format_) ) + ! TODO: + ! Implement onelab_Get method CALL e%raiseError(modName//"::"//myName//" - "// & - & "This routine is under construction.") + & "[WIP ERROR] :: This routine is under construction.") END FUNCTION onelab_Get !---------------------------------------------------------------------------- @@ -161,22 +156,22 @@ END FUNCTION onelab_Get ! Get the value of the number parameter `name` from the ONELAB database. ! Return an empty vector if the parameter does not exist. -FUNCTION onelab_GetNumber(obj, name, value, value_n) RESULT(ans) +FUNCTION onelab_GetNumber(obj, name, VALUE, value_n) RESULT(ans) CLASS(GmshOnelab_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: value(:) + CHARACTER(*), INTENT(IN) :: name + REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), OPTIONAL, INTENT(OUT) :: value_n INTEGER(I4B) :: ans !> Internal variables TYPE(C_PTR) :: cptr INTEGER(C_SIZE_T) :: value_n_ - CHARACTER(LEN=:), ALLOCATABLE, TARGET :: name_ + CHARACTER(:), ALLOCATABLE, TARGET :: name_ !> main name_ = TRIM(name)//C_NULL_CHAR CALL gmshOnelabGetNumber(C_LOC(name_), cptr, value_n_, ierr) - CALL Reallocate(value, INT(value_n_, I4B)) + CALL Reallocate(VALUE, INT(value_n_, I4B)) IF (PRESENT(value_n)) value_n = value_n_ - CALL C_PTR_TO_REAL_VEC(cptr=cptr, vec=value) + CALL C_PTR_TO_REAL_VEC(cptr=cptr, vec=VALUE) ans = INT(ierr, I4B) END FUNCTION onelab_GetNumber @@ -201,16 +196,16 @@ END FUNCTION onelab_GetNumber ! int *ierr); !``` -FUNCTION onelab_SetString(obj, name, value) RESULT(ans) +FUNCTION onelab_SetString(obj, name, VALUE) RESULT(ans) CLASS(GmshOnelab_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - CHARACTER(LEN=*), INTENT(IN) :: value + CHARACTER(*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: VALUE INTEGER(I4B) :: ans !> internal variables - CHARACTER(LEN=:), ALLOCATABLE, TARGET :: name_ - CHARACTER(LEN=:), ALLOCATABLE, TARGET :: value_ + CHARACTER(:), ALLOCATABLE, TARGET :: name_ + CHARACTER(:), ALLOCATABLE, TARGET :: value_ name_ = TRIM(name)//C_NULL_CHAR - value_ = TRIM(value)//C_NULL_CHAR + value_ = TRIM(VALUE)//C_NULL_CHAR CALL gmshOnelabSetString(C_LOC(name_), C_LOC(value_), & & LEN(value_, C_SIZE_T), ierr) ans = INT(ierr, I4B) @@ -237,27 +232,26 @@ END FUNCTION onelab_SetString ! int *ierr); !``` -FUNCTION onelab_GetString(obj, name, value, value_n) RESULT(ans) +FUNCTION onelab_GetString(obj, name, VALUE, value_n) RESULT(ans) CLASS(GmshOnelab_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - CHARACTER(LEN=:), ALLOCATABLE, INTENT(INOUT) :: value + CHARACTER(*), INTENT(IN) :: name + CHARACTER(:), ALLOCATABLE, INTENT(INOUT) :: VALUE INTEGER(I4B), OPTIONAL, INTENT(IN) :: value_n INTEGER(I4B) :: ans !> internal variables TYPE(C_PTR) :: ptrValue - CHARACTER(LEN=:), ALLOCATABLE, TARGET :: name_ + CHARACTER(:), ALLOCATABLE, TARGET :: name_ INTEGER(C_SIZE_T) :: value_n_ !> main name_ = TRIM(name)//C_NULL_CHAR CALL gmshOnelabGetString(C_LOC(name_), ptrValue, value_n_, ierr) IF (value_n_ .EQ. 0) THEN - value = "" + VALUE = "" ELSE - ALLOCATE (CHARACTER(LEN=value_n_) :: value) - CALL C2Fortran(C_String=ptrValue, F_STRING=value) + ALLOCATE (CHARACTER(value_n_) :: VALUE) + CALL C2Fortran(C_String=ptrValue, F_STRING=VALUE) END IF ans = INT(ierr, I4B) END FUNCTION onelab_GetString END MODULE GmshOnelab_Class -#endif \ No newline at end of file diff --git a/src/modules/GmshAPI/src/GmshOption_Class.F90 b/src/modules/GmshAPI/src/GmshOption_Class.F90 index 441bbfda1..ed53f8600 100644 --- a/src/modules/GmshAPI/src/GmshOption_Class.F90 +++ b/src/modules/GmshAPI/src/GmshOption_Class.F90 @@ -16,17 +16,19 @@ ! MODULE GmshOption_Class -USE GlobalData, ONLY: DFP => Real64, I4B => Int32, LGT +USE GlobalData, ONLY: DFP => REAL64, I4B => INT32, LGT USE GmshInterface USE GmshUtility USE CInterface USE ISO_C_BINDING IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "GMSHOPTION_CLASS" +CHARACTER(*), PARAMETER :: modName = "GMSHOPTION_CLASS" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: GmshOption_ +PUBLIC :: GmshOptionPointer_ !---------------------------------------------------------------------------- ! @@ -35,16 +37,15 @@ MODULE GmshOption_Class TYPE :: GmshOption_ CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: Initiate => opt_Initiate - PROCEDURE, PUBLIC, PASS(Obj) :: setNumber => opt_setNumber - PROCEDURE, PUBLIC, PASS(Obj) :: getNumber => opt_getNumber - PROCEDURE, PUBLIC, PASS(Obj) :: setString => opt_setString - PROCEDURE, PUBLIC, PASS(Obj) :: getString => opt_getString - PROCEDURE, PUBLIC, PASS(Obj) :: setColor => opt_setColor - PROCEDURE, PUBLIC, PASS(Obj) :: getColor => opt_getColor + PROCEDURE, PUBLIC, NOPASS :: Initiate => opt_Initiate + PROCEDURE, PUBLIC, NOPASS :: setNumber => opt_setNumber + PROCEDURE, PUBLIC, NOPASS :: getNumber => opt_getNumber + PROCEDURE, PUBLIC, NOPASS :: setString => opt_setString + PROCEDURE, PUBLIC, NOPASS :: getString => opt_getString + PROCEDURE, PUBLIC, NOPASS :: setColor => opt_setColor + PROCEDURE, PUBLIC, NOPASS :: getColor => opt_getColor END TYPE GmshOption_ -PUBLIC :: GmshOption_ TYPE(GmshOption_), PUBLIC, PARAMETER :: TypeGmshOption = GmshOption_() !---------------------------------------------------------------------------- @@ -55,8 +56,6 @@ MODULE GmshOption_Class CLASS(GmshOption_), POINTER :: Ptr => NULL() END TYPE -PUBLIC :: GmshOptionPointer_ - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -67,27 +66,25 @@ MODULE GmshOption_Class ! !---------------------------------------------------------------------------- -SUBROUTINE opt_Initiate(obj) - CLASS(GmshOption_), INTENT(INOUT) :: obj +SUBROUTINE opt_Initiate() END SUBROUTINE opt_Initiate !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION opt_setNumber(obj, name, value) RESULT(ans) - CLASS(GmshOption_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - CLASS(*), INTENT(IN) :: value +FUNCTION opt_setNumber(name, VALUE) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(*), INTENT(IN) :: VALUE INTEGER(I4B) :: ans ! Internal variables - CHARACTER(LEN=maxStrLen), TARGET :: name_ - !! + CHARACTER(maxStrLen), TARGET :: name_ + name_ = TRIM(name)//C_NULL_CHAR CALL gmshOptionSetNumber( & & name=C_LOC(name_), & - & value=gmsh_cdouble(value), & + & VALUE=gmsh_cdouble(VALUE), & & ierr=ans) ! ans = INT( ierr, KIND=I4B) END FUNCTION opt_setNumber @@ -96,83 +93,75 @@ END FUNCTION opt_setNumber ! !---------------------------------------------------------------------------- -FUNCTION opt_getNumber(obj, name, value) RESULT(ans) - CLASS(GmshOption_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - REAL(DFP), INTENT(OUT) :: value +FUNCTION opt_getNumber(name, VALUE) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name + REAL(DFP), INTENT(OUT) :: VALUE INTEGER(I4B) :: ans - !! + ! Internal variables - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ REAL(C_DOUBLE) :: val - !! + name_ = TRIM(name)//C_NULL_CHAR - !! + CALL gmshOptionGetNumber( & & name=C_LOC(name_), & - & value=val, & + & VALUE=val, & & ierr=ans) - !! - value = REAL(val, KIND=DFP) + + VALUE = REAL(val, KIND=DFP) END FUNCTION opt_getNumber !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION opt_setString(obj, name, value) RESULT(ans) - CLASS(GmshOption_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - CHARACTER(LEN=*), INTENT(IN) :: value +FUNCTION opt_setString(name, VALUE) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name + CHARACTER(*), INTENT(IN) :: VALUE INTEGER(I4B) :: ans - ! + ! Internal variables - CHARACTER(LEN=maxStrLen), TARGET :: name_, value_ - ! + CHARACTER(maxStrLen), TARGET :: name_, value_ + name_ = TRIM(name)//C_NULL_CHAR - value_ = TRIM(value)//C_NULL_CHAR - ! + value_ = TRIM(VALUE)//C_NULL_CHAR + CALL gmshOptionSetString(name=C_LOC(name_), & - & value=C_LOC(value_), ierr=ans) - ! + & VALUE=C_LOC(value_), ierr=ans) END FUNCTION opt_setString !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION opt_getString(obj, name, value) RESULT(ans) - CLASS(GmshOption_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name - CHARACTER(LEN=*), INTENT(OUT) :: value +FUNCTION opt_getString(name, VALUE) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name + CHARACTER(*), INTENT(OUT) :: VALUE INTEGER(I4B) :: ans - ! + ! Internal variables - ! - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ TYPE(C_PTR) :: value_ - ! + name_ = TRIM(name)//C_NULL_CHAR CALL gmshOptionGetString(name=C_LOC(name_), & - & value=value_, ierr=ans) - CALL C2Fortran(C_String=value_, F_String=value) - ! + & VALUE=value_, ierr=ans) + CALL C2Fortran(C_String=value_, F_String=VALUE) END FUNCTION opt_getString !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION opt_setColor(obj, name, r, g, b, a) RESULT(ans) - CLASS(GmshOption_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name +FUNCTION opt_setColor(name, r, g, b, a) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B), INTENT(IN) :: r, g, b, a INTEGER(I4B) :: ans - ! + ! Internal variables - ! - CHARACTER(LEN=maxStrLen), TARGET :: name_ - ! + CHARACTER(maxStrLen), TARGET :: name_ + name_ = gmsh_CString(name) CALL gmshOptionSetColor( & & name=C_LOC(name_), & @@ -181,29 +170,26 @@ FUNCTION opt_setColor(obj, name, r, g, b, a) RESULT(ans) & b=gmsh_cint(b), & & a=gmsh_cint(a), & & ierr=ans) - !! END FUNCTION opt_setColor !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -FUNCTION opt_getColor(obj, name, r, g, b, a) RESULT(ans) - CLASS(GmshOption_), INTENT(IN) :: obj - CHARACTER(LEN=*), INTENT(IN) :: name +FUNCTION opt_getColor(name, r, g, b, a) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name INTEGER(I4B), INTENT(OUT) :: r, g, b, a INTEGER(I4B) :: ans - ! + ! Internal variables - ! - CHARACTER(LEN=maxStrLen), TARGET :: name_ + CHARACTER(maxStrLen), TARGET :: name_ INTEGER(C_INT) :: r0, g0, b0, a0 - !! + name_ = gmsh_CString(name) CALL gmshOptionGetColor( & & name=C_LOC(name_), & & r=r0, g=g0, b=b0, a=a0, ierr=ans) - !! + r = INT(r0, KIND=I4B) g = INT(g0, KIND=I4B) b = INT(b0, KIND=I4B) diff --git a/src/modules/GmshAPI/src/GmshStructuredMesh_Class.F90 b/src/modules/GmshAPI/src/GmshStructuredMesh_Class.F90 new file mode 100644 index 000000000..6870e6072 --- /dev/null +++ b/src/modules/GmshAPI/src/GmshStructuredMesh_Class.F90 @@ -0,0 +1,1114 @@ +! 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 GmshStructuredMesh_Class +USE GlobalData +USE BaseType +USE String_Class, ONLY: String +USE ExceptionHandler_Class, ONLY: e +USE FPL, ONLY: ParameterList_ +USE FPL_Method +USE Gmsh_Class +USE BaseMethod +IMPLICIT NONE +PRIVATE +PUBLIC :: GmshStructuredMesh_ +PUBLIC :: GmshStructuredMeshPointer_ +PUBLIC :: SetGmshStructuredMeshParam +INTEGER(I4B), PARAMETER :: Progression = 1 +INTEGER(I4B), PARAMETER :: Bump = 2 +INTEGER(I4B), PUBLIC, PARAMETER :: GMSH_API_PROGRESSION = 1 +INTEGER(I4B), PUBLIC, PARAMETER :: GMSH_API_BUMP = 2 +CHARACTER(*), PARAMETER :: modName = "StructuredMesh_Class" +CHARACTER(*), PARAMETER :: myprefix = "StructuredMesh" +CHARACTER(*), PARAMETER :: MeshTypeName(2) = ["Progression", "Bump "] + +!---------------------------------------------------------------------------- +! GmshStructuredMesh_ +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-03 +! summary: The data type to create structured mesh by using Gmsh + +TYPE :: GmshStructuredMesh_ + ! PRIVATE + LOGICAL(LGT) :: recombineAll = .TRUE. + !! All surfaces will be recombine into quad or hexahedron + INTEGER(I4B) :: nsd = 2_I4B + !! Spatial dimension + TYPE(String) :: filename + !! Name of the mesh file to be generated + TYPE(RealMatrix_) :: points(3) + !! points on axis 1, axis 2, axis 3 + !! points(1) are points on axis 1 + !! points(2) are points on axis 2 + !! points(3) are points on axis 3 + INTEGER(I4B) :: tPoints(3) = 0 + !! Total points on axis 1 to define the region + !! Total points on axis 2 to define the region + !! Total points on axis 3 to define the region + REAL(DFP), ALLOCATABLE :: allPoints(:, :) + !! All the points + TYPE(IntVector_) :: transfinitePoints(3) + !! transfinitePoints on lines + !! transfinitePoints(1) is transfinitePoints on axis 1 + !! transfinitePoints(2) is transfinitePoints on axis 2 + !! transfinitePoints(3) is transfinitePoints on axis 3 + INTEGER(I4B), ALLOCATABLE :: edge_tfp(:) + !! transfinitePoints for transfinite curves + REAL(DFP), ALLOCATABLE :: edge_coef(:) + !! coef ofr transfinite curves + TYPE(String), ALLOCATABLE :: edge_meshType(:) + !! mesh type for transfinite curves + INTEGER(I4B), ALLOCATABLE :: edges(:, :) + !! The edges + INTEGER(I4B) :: tEdges1 = 0 + !! Total edges parallel to axis 1 + INTEGER(I4B) :: tEdges2 = 0 + !! Total edges parallel to axis 2 + INTEGER(I4B) :: tEdges3 = 0 + !! Total edges parallel to axis 3 + INTEGER(I4B) :: tEdges = 0 + !! Total number of edges = tEdges1+tEdges2+tEdges3 + INTEGER(I4B), ALLOCATABLE :: curveLoops(:, :) + !! Surface loops for boxes, it means boxes in terms of + !! edges + INTEGER(I4B) :: tSurfacesXY = 0 + !! Total number of surfaces parallen to XY plane + INTEGER(I4B) :: tSurfacesYZ = 0 + !! Total number of surfaces parallen to YZ plane + INTEGER(I4B) :: tSurfacesXZ = 0 + !! Total number of surfaces parallen to XZ plane + INTEGER(I4B) :: tSurfaces = 0 + !! Total number of surfaces + !! If there are no holes then tSurfaces equal to tVolumes + INTEGER(I4B) :: tVolumes = 0 + !! Total number of boxes + INTEGER(I4B), ALLOCATABLE :: surfaceLoops(:, :) + !! Surface loops for making volumes +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & mesh_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => mesh_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => mesh_Deallocate + PROCEDURE, PUBLIC, PASS(obj) :: Generate => mesh_Generate + PROCEDURE, PUBLIC, PASS(obj) :: GeneratePoints => mesh_GeneratePoints + PROCEDURE, PUBLIC, PASS(obj) :: GenerateCurves => mesh_GenerateCurves + PROCEDURE, PUBLIC, PASS(obj) :: GenerateSurfaces => mesh_GenerateSurfaces + PROCEDURE, PUBLIC, PASS(obj) :: GenerateVolumes => mesh_GenerateVolumes + PROCEDURE, PUBLIC, PASS(obj) :: Display => mesh_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetNodeNumber => mesh_GetNodeNumber + PROCEDURE, PUBLIC, PASS(obj) :: GetEdgeNumberOnAxis1 => & + & mesh_GetEdgeNumberOnAxis1 + PROCEDURE, PUBLIC, PASS(obj) :: GetEdgeNumberOnAxis2 => & + & mesh_GetEdgeNumberOnAxis2 + PROCEDURE, PUBLIC, PASS(obj) :: GetEdgeNumberOnAxis3 => & + & mesh_GetEdgeNumberOnAxis3 + PROCEDURE, PUBLIC, PASS(obj) :: GetSurfaceNumberXY => & + & mesh_GetSurfaceNumberXY + PROCEDURE, PUBLIC, PASS(obj) :: GetSurfaceNumberYZ => & + & mesh_GetSurfaceNumberYZ + PROCEDURE, PUBLIC, PASS(obj) :: GetSurfaceNumberXZ => & + & mesh_GetSurfaceNumberXZ +END TYPE GmshStructuredMesh_ + +!---------------------------------------------------------------------------- +! GmshStructuredMeshPointer_ +!---------------------------------------------------------------------------- + +TYPE :: GmshStructuredMeshPointer_ + CLASS(GmshStructuredMesh_), POINTER :: ptr => NULL() +END TYPE GmshStructuredMeshPointer_ + +!---------------------------------------------------------------------------- +! Contains +!---------------------------------------------------------------------------- + +CONTAINS + +!---------------------------------------------------------------------------- +! SetGmshStructuredMeshParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Set parameter + +SUBROUTINE SetGmshStructuredMeshParam( & + & param, & + & filename, & + & pointsOnAxis1, & + & transfinitePointsOnAxis1, & + & pointsOnAxis2, & + & transfinitePointsOnAxis2, & + & pointsOnAxis3, & + & transfinitePointsOnAxis3, & + & recombineAll, & + & meshTypeOnAxis1, & + & meshTypeOnAxis2, & + & meshTypeOnAxis3, & + & coefOnAxis1, & + & coefOnAxis2, & + & coefOnAxis3) + TYPE(ParameterList_), INTENT(INOUT) :: param + !! spatial dimension + CHARACTER(*), INTENT(IN) :: filename + !! name of the mesh file to be generated + REAL(DFP), INTENT(IN) :: pointsOnAxis1(:, :) + !! points on axis 1 + INTEGER(I4B), INTENT(IN) :: transfinitePointsOnAxis1(:) + !! transfinitePoints on axis 1 + REAL(DFP), INTENT(IN) :: pointsOnAxis2(:, :) + !! points on axis 2 + INTEGER(I4B), INTENT(IN) :: transfinitePointsOnAxis2(:) + !! transfinitePoints on axis 2 + REAL(DFP), OPTIONAL, INTENT(IN) :: pointsOnAxis3(:, :) + !! points on axis 3 + INTEGER(I4B), OPTIONAL, INTENT(IN) :: transfinitePointsOnAxis3(:) + !! transfinitePoints on axis 3 + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: recombineAll + !! If true we combine triangle and tetrahedron into quad and hexahedron + INTEGER(I4B), OPTIONAL, INTENT(IN) :: meshTypeOnAxis1(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: meshTypeOnAxis2(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: meshTypeOnAxis3(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: coefOnAxis1(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: coefOnAxis2(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: coefOnAxis3(:) + + ! internal variables + INTEGER(I4B) :: tPoints(3), tVolumes, aint, bint, nsd + REAL(DFP), ALLOCATABLE :: pointsOnAxis3_(:, :) + REAL(DFP), ALLOCATABLE :: coefOnAxis1_(:) + REAL(DFP), ALLOCATABLE :: coefOnAxis2_(:) + REAL(DFP), ALLOCATABLE :: coefOnAxis3_(:) + INTEGER(I4B), ALLOCATABLE :: meshTypeOnAxis1_(:) + INTEGER(I4B), ALLOCATABLE :: meshTypeOnAxis2_(:) + INTEGER(I4B), ALLOCATABLE :: meshTypeOnAxis3_(:) + INTEGER(I4B), ALLOCATABLE :: transfinitePointsOnAxis3_(:) + REAL(DFP), PARAMETER :: r2type(1, 1) = 0, r1type(1) = 0.0_DFP + INTEGER(I4B), PARAMETER :: i1type(1) = 0 + CHARACTER(*), PARAMETER :: myName = "SetGmshStructuredMesh2DParam()" + LOGICAL(LGT) :: recombineAll_ + + aint = SIZE(pointsOnAxis1, 1) + IF (aint .NE. 3_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The number of rows in pointsOnAxis1 should be 3'// & + & ' but it is '//tostring(aint)) + END IF + + aint = SIZE(pointsOnAxis1, 2) + bint = SIZE(transfinitePointsOnAxis1) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: SIZE(pointsOnAxis1, 2) should be same as '// & + & ' number of transfinitePointsOnAxis1 + 1'// & + & ' but '//tostring(aint)//"!="//tostring(bint + 1)) + END IF + + aint = SIZE(pointsOnAxis2, 1) + IF (aint .NE. 3_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis2, 1) should be 3'// & + & ' but it is '//tostring(aint)) + END IF + + aint = SIZE(pointsOnAxis2, 2) + bint = SIZE(transfinitePointsOnAxis2) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis2, 2) should be same as '// & + & ' number of transfinitePointsOnAxis2 + 1'// & + & ' but '//tostring(aint)//"!="//tostring(bint + 1)) + END IF + + tPoints = 1 + tPoints(1) = SIZE(pointsOnAxis1, 2) + tPoints(2) = SIZE(pointsOnAxis2, 2) + + IF (PRESENT(pointsOnAxis3)) THEN + nsd = 3 + aint = SIZE(pointsOnAxis3, 1) + IF (aint .NE. 3_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis3, 1) should be 3'// & + & ' but it is '//tostring(aint)) + END IF + + IF (.NOT. PRESENT(transfinitePointsOnAxis3)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: transfinitePointsOnAxis3 should be present '// & + & 'when pointsOnAxis3 are present.') + END IF + + aint = SIZE(pointsOnAxis3, 2) + bint = SIZE(transfinitePointsOnAxis3) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis3, 2) should be same as '// & + & ' number of transfinitePointsOnAxis3 + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + + tPoints(3) = SIZE(pointsOnAxis3, 2) + pointsOnAxis3_ = pointsOnAxis3 + transfinitePointsOnAxis3_ = transfinitePointsOnAxis3 + ELSE + nsd = 2 + CALL Reallocate(pointsOnAxis3_, 3_I4B, 1_I4B) + CALL Reallocate(transfinitePointsOnAxis3_, 1_I4B) + pointsOnAxis3_ = pointsOnAxis1(:, 1:1) + transfinitePointsOnAxis3_ = [1] + END IF + + IF (PRESENT(meshTypeOnAxis1)) THEN + aint = SIZE(pointsOnAxis1, 2) + bint = SIZE(meshTypeOnAxis1) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis1, 2) should be same as '// & + & ' number of size(meshTypeOnAxis1) + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + meshTypeOnAxis1_ = meshTypeOnAxis1 + ELSE + CALL Reallocate(meshTypeOnAxis1_, tPoints(1) - 1) + meshTypeOnAxis1_ = Progression + END IF + + IF (PRESENT(meshTypeOnAxis2)) THEN + aint = SIZE(pointsOnAxis2, 2) + bint = SIZE(meshTypeOnAxis2) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis2, 2) should be same as '// & + & ' number of size(meshTypeOnAxis2) + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + meshTypeOnAxis2_ = meshTypeOnAxis2 + ELSE + CALL Reallocate(meshTypeOnAxis2_, tPoints(2) - 1) + meshTypeOnAxis2_ = Progression + END IF + + IF (PRESENT(meshTypeOnAxis3)) THEN + aint = SIZE(pointsOnAxis3, 2) + bint = SIZE(meshTypeOnAxis3) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis3, 2) should be same as '// & + & ' number of size(meshTypeOnAxis3) + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + meshTypeOnAxis3_ = meshTypeOnAxis3 + ELSE + CALL Reallocate(meshTypeOnAxis3_, tPoints(3) - 1) + meshTypeOnAxis3_ = Progression + END IF + + IF (PRESENT(coefOnAxis1)) THEN + aint = SIZE(pointsOnAxis1, 2) + bint = SIZE(coefOnAxis1) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis1, 2) should be same as '// & + & ' number of size(coefOnAxis1) + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + coefOnAxis1_ = coefOnAxis1 + ELSE + CALL Reallocate(coefOnAxis1_, tPoints(1) - 1) + coefOnAxis1_ = 1.0_DFP + END IF + + IF (PRESENT(coefOnAxis2)) THEN + aint = SIZE(pointsOnAxis2, 2) + bint = SIZE(coefOnAxis2) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis2, 2) should be same as '// & + & ' number of size(coefOnAxis2) + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + coefOnAxis2_ = coefOnAxis2 + ELSE + CALL Reallocate(coefOnAxis2_, tPoints(2) - 1) + coefOnAxis2_ = 1.0_DFP + END IF + + IF (PRESENT(coefOnAxis3)) THEN + aint = SIZE(pointsOnAxis3, 2) + bint = SIZE(coefOnAxis3) + IF (aint .NE. bint + 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: size(pointsOnAxis3, 2) should be same as '// & + & ' number of size(coefOnAxis3) + 1'// & + & ' but '//tostring(aint)//'!='//tostring(bint + 1)) + END IF + coefOnAxis3_ = coefOnAxis3 + ELSE + CALL Reallocate(coefOnAxis3_, tPoints(3) - 1) + coefOnAxis3_ = 1.0_DFP + END IF + + recombineAll_ = input(option=recombineAll, default=.TRUE.) + CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="recombineAll", & + & VALUE=recombineAll_) + + CALL Set(obj=param, datatype="char", prefix=myprefix, key="filename", & + & VALUE=filename) + + CALL Set(obj=param, datatype=TypeIntI4B, prefix=myprefix, key="nsd", & + & VALUE=nsd) + + tVolumes = MAX(tPoints(1) - 1, 1_I4B) * MAX(tPoints(2) - 1, 1_I4B) * & + & MAX(tPoints(3) - 1, 1_I4B) + + CALL Set(obj=param, datatype=1_I4B, prefix=myprefix, key="tVolumes", & + & VALUE=tVolumes) + + CALL Set(obj=param, datatype=[1_I4B], prefix=myprefix, key="tPoints", & + & VALUE=tPoints) + + CALL Set(obj=param, datatype=r2type, prefix=myprefix, & + & key="pointsOnAxis1", VALUE=pointsOnAxis1) + + CALL Set(obj=param, datatype=r2type, prefix=myprefix, & + & key="pointsOnAxis2", VALUE=pointsOnAxis2) + + CALL Set(obj=param, datatype=r2type, prefix=myprefix, & + & key="pointsOnAxis3", VALUE=pointsOnAxis3_) + + CALL Set(obj=param, datatype=i1type, prefix=myprefix, & + & key="transfinitePointsOnAxis1", VALUE=transfinitePointsOnAxis1) + + CALL Set(obj=param, datatype=i1type, prefix=myprefix, & + & key="transfinitePointsOnAxis2", VALUE=transfinitePointsOnAxis2) + + CALL Set(obj=param, datatype=i1type, prefix=myprefix, & + & key="transfinitePointsOnAxis3", VALUE=transfinitePointsOnAxis3_) + + CALL Set(obj=param, datatype=i1type, prefix=myprefix, & + & key="meshTypeOnAxis1", VALUE=meshTypeOnAxis1_) + + CALL Set(obj=param, datatype=i1type, prefix=myprefix, & + & key="meshTypeOnAxis2", VALUE=meshTypeOnAxis2_) + + CALL Set(obj=param, datatype=i1type, prefix=myprefix, & + & key="meshTypeOnAxis3", VALUE=meshTypeOnAxis3_) + + CALL Set(obj=param, datatype=r1type, prefix=myprefix, & + & key="coefOnAxis1", VALUE=coefOnAxis1_) + + CALL Set(obj=param, datatype=r1type, prefix=myprefix, & + & key="coefOnAxis2", VALUE=coefOnAxis2_) + + CALL Set(obj=param, datatype=r1type, prefix=myprefix, & + & key="coefOnAxis3", VALUE=coefOnAxis3_) + + IF (ALLOCATED(pointsOnAxis3_)) DEALLOCATE (pointsOnAxis3_) + IF (ALLOCATED(coefOnAxis1_)) DEALLOCATE (coefOnAxis1_) + IF (ALLOCATED(coefOnAxis2_)) DEALLOCATE (coefOnAxis2_) + IF (ALLOCATED(coefOnAxis3_)) DEALLOCATE (coefOnAxis3_) + + IF (ALLOCATED(meshTypeOnAxis1_)) DEALLOCATE (meshTypeOnAxis1_) + IF (ALLOCATED(meshTypeOnAxis2_)) DEALLOCATE (meshTypeOnAxis2_) + IF (ALLOCATED(meshTypeOnAxis3_)) DEALLOCATE (meshTypeOnAxis3_) + + IF (ALLOCATED(transfinitePointsOnAxis3_)) & + & DEALLOCATE (transfinitePointsOnAxis3_) +END SUBROUTINE SetGmshStructuredMeshParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Check essential parameters + +SUBROUTINE mesh_CheckEssentialParam(obj, param) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + + ! internal variables + CHARACTER(*), PARAMETER :: myName = "mesh_CheckEssentialParam()" + TYPE(String) :: astr + TYPE(String), ALLOCATABLE :: essentialParam(:) + INTEGER(I4B) :: ii + + astr = "/filename/tVolumes/tPoints/pointsOnAxis1/pointsOnAxis2/"// & + & "pointsOnAxis3/transfinitePointsOnAxis1/transfinitePointsOnAxis2/"// & + & "transfinitePointsOnAxis3/recombineAll/meshTypeOnAxis1/"// & + & "meshTypeOnAxis2/meshTypeOnAxis3/coefOnAxis1/coefOnAxis2/"// & + & "coefOnAxis3/nsd" + + CALL astr%Split(essentialParam, sep="/") + + CALL CheckEssentialParam( & + & obj=param, & + & keys=essentialParam, & + & prefix=myprefix, & + & myName=myName, & + & modName=modName) + + IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" + END DO + DEALLOCATE (essentialParam) + END IF + + astr = "" + +END SUBROUTINE mesh_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Initiate the object + +SUBROUTINE mesh_Initiate(obj, param) + CLASS(GmshStructuredMesh_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + + ! internal variables + INTEGER(I4B) :: ii, jj, kk, ipoint, iedge, lineLoop(4), tedges(3), & + & isurface, te(3), p(2), tsurfaces(3), iVolume, surfaceLoops(6) + REAL(DFP), ALLOCATABLE :: pointsOnAxis1(:, :), pointsOnAxis2(:, :), & + & pointsOnAxis3(:, :), coefOnAxis1(:), coefOnAxis2(:), coefOnAxis3(:), & + & dummy_real_r2(:, :) + INTEGER(I4B), ALLOCATABLE :: meshTypeOnAxis1(:), meshTypeOnAxis2(:), & + & meshTypeOnAxis3(:) + CHARACTER(*), PARAMETER :: myName = "mesh_Initiate()" + + CALL obj%DEALLOCATE() + + CALL obj%CheckEssentialParam(param) + + CALL GetValue(obj=param, prefix=myprefix, key="recombineAll", & + & VALUE=obj%recombineAll) + + CALL GetValue(obj=param, prefix=myprefix, key="filename", & + & VALUE=obj%filename) + + CALL GetValue(obj=param, prefix=myprefix, key="tVolumes", & + & VALUE=obj%tVolumes) + + CALL GetValue(obj=param, prefix=myprefix, key="tPoints", & + & VALUE=obj%tPoints) + + CALL GetValue(obj=param, prefix=myprefix, key="nsd", & + & VALUE=obj%nsd) + + te = obj%tPoints - 1 + + DO ii = 1, 3 + CALL Initiate(obj%points(ii), 3_I4B, obj%tPoints(ii)) + CALL GetValue(obj=param, prefix=myprefix, & + & key="pointsOnAxis"//tostring(ii), VALUE=obj%points(ii)) + END DO + + ALLOCATE (pointsOnAxis1(3, 0:obj%tPoints(1))) + ALLOCATE (pointsOnAxis2(3, 0:obj%tPoints(2))) + ALLOCATE (pointsOnAxis3(3, 0:obj%tPoints(3))) + pointsOnAxis1 = 0.0_DFP + pointsOnAxis2 = 0.0_DFP + pointsOnAxis3 = 0.0_DFP + + pointsOnAxis1(1:3, 1:) = Get(obj%points(1)) + pointsOnAxis2(1:3, 1:) = Get(obj%points(2)) + pointsOnAxis3(1:3, 1:) = Get(obj%points(3)) + + ipoint = obj%tPoints(1) * obj%tPoints(2) * obj%tPoints(3) + CALL Reallocate(obj%allPoints, 3_I4B, ipoint) + + ipoint = 0 + DO kk = 1, obj%tpoints(3) + DO jj = 1, obj%tPoints(2) + DO ii = 1, obj%tPoints(1) + ipoint = ipoint + 1 + ! obj%allPoints(:, ipoint) = [pointsOnAxis1(1, ii), & + ! & pointsOnAxis2(2, jj), & + ! & pointsOnAxis3(3, kk)] + obj%allPoints(:, ipoint) = pointsOnAxis1(:, ii - 1) & + & + pointsOnAxis1(:, ii) - pointsOnAxis1(:, ii - 1) & + & + pointsOnAxis2(:, jj) - pointsOnAxis2(:, jj - 1) & + & + pointsOnAxis3(:, kk) - pointsOnAxis3(:, kk - 1) + END DO + END DO + END DO + + CALL Reallocate(meshTypeOnAxis1, MAX(te(1), 1_I4B)) + CALL Reallocate(meshTypeOnAxis2, MAX(te(2), 1_I4B)) + CALL Reallocate(meshTypeOnAxis3, MAX(te(3), 1_I4B)) + + CALL Reallocate(coefOnAxis1, MAX(te(1), 1_I4B)) + CALL Reallocate(coefOnAxis2, MAX(te(2), 1_I4B)) + CALL Reallocate(coefOnAxis3, MAX(te(3), 1_I4B)) + + CALL GetValue(obj=param, prefix=myprefix, & + & key="meshTypeOnAxis1", VALUE=meshTypeOnAxis1) + + CALL GetValue(obj=param, prefix=myprefix, & + & key="meshTypeOnAxis2", VALUE=meshTypeOnAxis2) + + CALL GetValue(obj=param, prefix=myprefix, & + & key="meshTypeOnAxis3", VALUE=meshTypeOnAxis3) + + CALL GetValue(obj=param, prefix=myprefix, & + & key="coefOnAxis1", VALUE=coefOnAxis1) + + CALL GetValue(obj=param, prefix=myprefix, & + & key="coefOnAxis2", VALUE=coefOnAxis2) + + CALL GetValue(obj=param, prefix=myprefix, & + & key="coefOnAxis3", VALUE=coefOnAxis3) + + DO ii = 1, 3 + CALL Initiate(obj%transfinitePoints(ii), & + & MAX(te(ii), 1_I4B)) + CALL GetValue(obj=param, prefix=myprefix, & + & key="transfinitePointsOnAxis"//tostring(ii), & + & VALUE=obj%transfinitePoints(ii)) + END DO + + tedges(1) = te(1) * obj%tPoints(2) * obj%tPoints(3) + tedges(2) = te(2) * obj%tPoints(3) * obj%tPoints(1) + tedges(3) = te(3) * obj%tPoints(2) * obj%tPoints(1) + + obj%tEdges1 = tedges(1) + obj%tEdges2 = tedges(2) + obj%tEdges3 = tedges(3) + + obj%tEdges = tedges(1) + tedges(2) + tedges(3) + + CALL Reallocate(obj%edges, 2, obj%tEdges) + CALL Reallocate(obj%edge_tfp, obj%tEdges) + CALL Reallocate(obj%edge_meshType, obj%tEdges) + CALL Reallocate(obj%edge_coef, obj%tEdges) + + ! edges parallel to axis 1 + iedge = 0 + DO kk = 1, obj%tPoints(3) + DO jj = 1, obj%tPoints(2) + DO ii = 1, obj%tPoints(1) - 1 + p(1) = obj%GetNodeNumber(ii, jj, kk) + p(2) = obj%GetNodeNumber(ii + 1, jj, kk) + iedge = iedge + 1 + obj%edges(:, iedge) = p + obj%edge_tfp(iedge) = Get(obj%transfinitePoints(1), ii, 1_I4B) + obj%edge_coef(iedge) = coefOnAxis1(ii) + obj%edge_meshType(iedge) = MeshTypeName(meshTypeOnAxis1(ii)) + END DO + END DO + END DO + + ! edges parallel to axis 2 + DO kk = 1, obj%tPoints(3) + DO jj = 1, obj%tPoints(2) - 1 + DO ii = 1, obj%tPoints(1) + p(1) = obj%GetNodeNumber(ii, jj, kk) + p(2) = obj%GetNodeNumber(ii, jj + 1, kk) + iedge = iedge + 1 + obj%edges(:, iedge) = p + obj%edge_tfp(iedge) = Get(obj%transfinitePoints(2), jj, 1_I4B) + obj%edge_coef(iedge) = coefOnAxis2(jj) + obj%edge_meshType(iedge) = MeshTypeName(meshTypeOnAxis2(jj)) + END DO + END DO + END DO + + ! edges parallel to axis 3 + DO kk = 1, obj%tPoints(3) - 1 + DO jj = 1, obj%tPoints(2) + DO ii = 1, obj%tPoints(1) + p(1) = obj%GetNodeNumber(ii, jj, kk) + p(2) = obj%GetNodeNumber(ii, jj, kk + 1) + iedge = iedge + 1 + obj%edges(:, iedge) = p + obj%edge_tfp(iedge) = Get(obj%transfinitePoints(3), kk, 1_I4B) + obj%edge_coef(iedge) = coefOnAxis3(kk) + obj%edge_meshType(iedge) = MeshTypeName(meshTypeOnAxis3(kk)) + END DO + END DO + END DO + + ! xy + tsurfaces(1) = te(1) * te(2) * obj%tPoints(3) + ! yz + tsurfaces(2) = te(2) * te(3) * obj%tPoints(1) + ! xz + tsurfaces(3) = te(1) * te(3) * obj%tPoints(2) + + obj%tSurfacesXY = tsurfaces(1) + obj%tSurfacesYZ = tsurfaces(2) + obj%tSurfacesXZ = tsurfaces(3) + + obj%tSurfaces = tsurfaces(1) + tsurfaces(2) + tsurfaces(3) + + CALL Reallocate(obj%curveLoops, 4, obj%tSurfaces) + + isurface = 0 + ! xy (1-2) + DO kk = 1, obj%tPoints(3) + DO jj = 1, obj%tPoints(2) - 1 + DO ii = 1, obj%tPoints(1) - 1 + isurface = isurface + 1 + lineLoop(1) = obj%GetEdgeNumberOnAxis1(ii, jj, kk) + lineLoop(3) = obj%GetEdgeNumberOnAxis1(ii, jj + 1, kk) + lineLoop(2) = obj%GetEdgeNumberOnAxis2(ii + 1, jj, kk) + lineLoop(4) = obj%GetEdgeNumberOnAxis2(ii, jj, kk) + obj%curveLoops(:, isurface) = [lineLoop(1), lineLoop(2), & + & -lineLoop(3), -lineLoop(4)] + END DO + END DO + END DO + + ! yz (2-3) + DO ii = 1, obj%tPoints(1) + DO kk = 1, obj%tPoints(3) - 1 + DO jj = 1, obj%tPoints(2) - 1 + isurface = isurface + 1 + lineLoop(1) = obj%GetEdgeNumberOnAxis2(ii, jj, kk) + lineLoop(3) = obj%GetEdgeNumberOnAxis2(ii, jj, kk + 1) + lineLoop(2) = obj%GetEdgeNumberOnAxis3(ii, jj + 1, kk) + lineLoop(4) = obj%GetEdgeNumberOnAxis3(ii, jj, kk) + obj%curveLoops(:, isurface) = [lineLoop(1), lineLoop(2), & + & -lineLoop(3), -lineLoop(4)] + END DO + END DO + END DO + + ! xz (1-3) + DO jj = 1, obj%tPoints(2) + DO kk = 1, obj%tPoints(3) - 1 + DO ii = 1, obj%tPoints(1) - 1 + isurface = isurface + 1 + + lineLoop(1) = obj%GetEdgeNumberOnAxis1(ii, jj, kk) + lineLoop(3) = obj%GetEdgeNumberOnAxis1(ii, jj, kk + 1) + lineLoop(2) = obj%GetEdgeNumberOnAxis3(ii + 1, jj, kk) + lineLoop(4) = obj%GetEdgeNumberOnAxis3(ii, jj, kk) + + obj%curveLoops(:, isurface) = [lineLoop(1), lineLoop(2), & + & -lineLoop(3), -lineLoop(4)] + END DO + END DO + END DO + + ! making volumes + IF (obj%tVolumes .GT. 0_I4B) THEN + CALL Reallocate(obj%surfaceLoops, 6_I4B, obj%tVolumes) + ELSE + CALL Reallocate(obj%surfaceLoops, 0_I4B, 0_I4B) + END IF + + iVolume = 0_I4B + DO kk = 1, obj%tPoints(3) - 1 + DO jj = 1, obj%tPoints(2) - 1 + DO ii = 1, obj%tPoints(1) - 1 + iVolume = iVolume + 1 + surfaceLoops(1) = obj%GetSurfaceNumberXY(ii, jj, kk) + surfaceLoops(2) = obj%GetSurfaceNumberXY(ii, jj, kk + 1) + + surfaceLoops(3) = obj%GetSurfaceNumberYZ(ii, jj, kk) + surfaceLoops(4) = obj%GetSurfaceNumberYZ(ii + 1, jj, kk) + + surfaceLoops(5) = obj%GetSurfaceNumberXZ(ii, jj, kk) + surfaceLoops(6) = obj%GetSurfaceNumberXZ(ii, jj + 1, kk) + obj%surfaceLoops(:, iVolume) = surfaceLoops + END DO + END DO + END DO + + IF (ALLOCATED(pointsOnAxis1)) DEALLOCATE (pointsOnAxis1) + IF (ALLOCATED(pointsOnAxis2)) DEALLOCATE (pointsOnAxis2) + IF (ALLOCATED(pointsOnAxis3)) DEALLOCATE (pointsOnAxis3) + + IF (ALLOCATED(coefOnAxis1)) DEALLOCATE (coefOnAxis1) + IF (ALLOCATED(coefOnAxis2)) DEALLOCATE (coefOnAxis2) + IF (ALLOCATED(coefOnAxis3)) DEALLOCATE (coefOnAxis3) + + IF (ALLOCATED(meshTypeOnAxis1)) DEALLOCATE (meshTypeOnAxis1) + IF (ALLOCATED(meshTypeOnAxis2)) DEALLOCATE (meshTypeOnAxis2) + IF (ALLOCATED(meshTypeOnAxis3)) DEALLOCATE (meshTypeOnAxis3) + +END SUBROUTINE mesh_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Deallocate data + +SUBROUTINE mesh_Deallocate(obj) + CLASS(GmshStructuredMesh_), INTENT(INOUT) :: obj + INTEGER(I4B) :: ii + + DO ii = 1, SIZE(obj%points) + CALL DEALLOCATE (obj%points(ii)) + END DO + + DO ii = 1, 3 + CALL DEALLOCATE (obj%transfinitePoints(ii)) + END DO + obj%tPoints = 0 + + IF (ALLOCATED(obj%allPoints)) DEALLOCATE (obj%allPoints) + + IF (ALLOCATED(obj%edges)) DEALLOCATE (obj%edges) + IF (ALLOCATED(obj%edge_tfp)) DEALLOCATE (obj%edge_tfp) + IF (ALLOCATED(obj%edge_coef)) DEALLOCATE (obj%edge_coef) + IF (ALLOCATED(obj%edge_meshType)) DEALLOCATE (obj%edge_meshType) + obj%tEdges = 0 + + IF (ALLOCATED(obj%curveLoops)) DEALLOCATE (obj%curveLoops) + obj%tSurfaces = 0 + +END SUBROUTINE mesh_Deallocate + +!---------------------------------------------------------------------------- +! Generate +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-03 +! summary: Generate mesh + +SUBROUTINE mesh_Generate(obj, gmsh) + CLASS(GmshStructuredMesh_), INTENT(inout) :: obj + CLASS(Gmsh_), INTENT(INOUT) :: gmsh + + ! internal variables + INTEGER(I4B) :: ierr + + CALL obj%GeneratePoints(gmsh) + CALL obj%GenerateCurves(gmsh) + CALL obj%GenerateSurfaces(gmsh) + ierr = gmsh%model%geo%Synchronize() + ierr = gmsh%option%SetNumber(name="Mesh.SaveAll", VALUE=1_I4B) + ierr = gmsh%model%mesh%Generate(obj%nsd) + ierr = gmsh%WRITE(obj%filename%chars()) +END SUBROUTINE mesh_Generate + +!---------------------------------------------------------------------------- +! GeneratePoints +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Generate points + +SUBROUTINE mesh_GeneratePoints(obj, gmsh) + CLASS(GmshStructuredMesh_), INTENT(INOUT) :: obj + CLASS(Gmsh_), INTENT(INOUT) :: gmsh + ! internal variables + INTEGER(I4B) :: ipoint, ierr + + DO ipoint = 1, SIZE(obj%allPoints, 2) + ierr = gmsh%model%geo%addPoint( & + & x=obj%allPoints(1, ipoint), & + & y=obj%allPoints(2, ipoint), & + & z=obj%allPoints(3, ipoint), & + & meshSize=1.0_DFP) + END DO +END SUBROUTINE mesh_GeneratePoints + +!---------------------------------------------------------------------------- +! GenerateCurves +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Generate curves + +SUBROUTINE mesh_GenerateCurves(obj, gmsh) + CLASS(GmshStructuredMesh_), INTENT(INOUT) :: obj + CLASS(Gmsh_), INTENT(INOUT) :: gmsh + + ! internal variables + INTEGER(I4B) :: iedge, ierr + + DO iedge = 1, obj%tEdges + ierr = gmsh%model%geo%AddLine(obj%edges(1, iedge), obj%edges(2, iedge)) + ierr = gmsh%model%geo%mesh%SetTransfiniteCurve(tag=iedge, & + & nPoints=obj%edge_tfp(iedge), & + & meshType=obj%edge_meshType(iedge)%chars(), & + & coef=obj%edge_coef(iedge)) + END DO + +END SUBROUTINE mesh_GenerateCurves + +!---------------------------------------------------------------------------- +! GenerateSurfaces +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Generate Surfaces + +SUBROUTINE mesh_GenerateSurfaces(obj, gmsh) + CLASS(GmshStructuredMesh_), INTENT(INOUT) :: obj + CLASS(Gmsh_), INTENT(INOUT) :: gmsh + + ! Internal variables + CHARACTER(*), PARAMETER :: myName = "mesh_GenerateSurfaces()" + INTEGER(I4B) :: isurf, ierr + + DO isurf = 1, obj%tSurfaces + ierr = gmsh%model%geo%AddCurveLoop( & + & curveTags=obj%curveLoops(:, isurf), & + & reorient=.TRUE.) + END DO + + DO isurf = 1, obj%tSurfaces + ierr = gmsh%model%geo%AddPlaneSurface(wireTags=[isurf]) + ierr = gmsh%model%geo%mesh%SetTransfiniteSurface(tag=isurf) + END DO + + IF (obj%recombineAll) THEN + DO isurf = 1, obj%tSurfaces + ierr = gmsh%model%geo%mesh%SetRecombine(dim=2_I4B, tag=isurf) + END DO + END IF +END SUBROUTINE mesh_GenerateSurfaces + +!---------------------------------------------------------------------------- +! GenerateVolumes +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Generate Volumes + +SUBROUTINE mesh_GenerateVolumes(obj, gmsh) + CLASS(GmshStructuredMesh_), INTENT(INOUT) :: obj + CLASS(Gmsh_), INTENT(INOUT) :: gmsh + + CHARACTER(*), PARAMETER :: myName = "mesh_GenerateVolumes" + + ! Internal variables + INTEGER(I4B) :: iVolume, ierr + + DO iVolume = 1, obj%tVolumes + ierr = gmsh%model%geo%AddSurfaceLoop( & + & surfaceTags=obj%surfaceLoops(:, iVolume)) + END DO + + DO iVolume = 1, obj%tVolumes + ierr = gmsh%model%geo%AddVolume(shellTags=[iVolume]) + ierr = gmsh%model%geo%mesh%SetTransfiniteVolume(tag=iVolume) + END DO + + IF (obj%recombineAll) THEN + DO iVolume = 1, obj%tVolumes + ierr = gmsh%model%geo%mesh%SetRecombine(dim=3_I4B, tag=iVolume) + END DO + END IF +END SUBROUTINE mesh_GenerateVolumes + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-04 +! summary: Display the content + +SUBROUTINE mesh_Display(obj, msg, unitNo) + CLASS(GmshStructuredMesh_), INTENT(inout) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + + ! internal variables + IF (obj%recombineAll) THEN + CALL Display("recombineAll : TRUE", unitNo=unitNo) + ELSE + CALL Display("recombineAll : FALSE", unitNo=unitNo) + END IF + + CALL Display(obj%nsd, "nsd : ", unitNo=unitNo) + CALL Display(TRIM(obj%filename), "filename : ", unitNo=unitNo) + CALL Display(obj%tVolumes, "tVolumes : ", unitNo=unitNo) + CALL Display(obj%tPoints, "tPoints : ", unitNo=unitNo) + CALL Display(obj%points(1), "pointsOnAxis1 : ", unitNo=unitNo) + CALL Display(obj%points(2), "pointsOnAxis2 : ", unitNo=unitNo) + CALL Display(obj%points(3), "pointsOnAxis3 : ", unitNo=unitNo) + CALL Display(obj%allPoints, "All Points : ", unitNo=unitNo) + + CALL Display(obj%transfinitePoints(1), "transfinitePointsOnAxis1: ", & + & unitNo=unitNo) + CALL Display(obj%transfinitePoints(2), "transfinitePointsOnAxis2: ", & + & unitNo=unitNo) + CALL Display(obj%transfinitePoints(3), "transfinitePointsOnAxis3: ", & + & unitNo=unitNo) + CALL Display(obj%edge_tfp, "Transfinite Points : ", & + & unitNo=unitNo) + CALL Display(obj%edge_coef, "Transfinite coef : ", & + & unitNo=unitNo) + ! CALL Display(obj%edge_meshType, "Transfinite meshType : ", & + ! & unitNo=unitNo) + CALL Display(obj%edges, "Edges : ", & + & unitNo=unitNo) + CALL Display(obj%tEdges, "Total edges : ", & + & unitNo=unitNo) + CALL Display(obj%curveLoops, "SurfaceLoops : ", & + & unitNo=unitNo) + CALL Display(obj%tSurfaces, "Total surfaces : ", & + & unitNo=unitNo) + CALL Display(obj%edges, "edges : ", unitNo=unitNo) +END SUBROUTINE mesh_Display + +!---------------------------------------------------------------------------- +! GetNodeNumber +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetNodeNumber(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ni, nj, nk, ii, jj, kk + + ii = i; jj = j; kk = k; ni = obj%tPoints(1); nj = obj%tPoints(2) + nk = obj%tPoints(3) + ans = (j - 1) * ni + i + (k - 1) * ni * nj +END FUNCTION mesh_GetNodeNumber + +!---------------------------------------------------------------------------- +! GetEdgeNumberOnAxis1 +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetEdgeNumberOnAxis1(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + !! point number + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ii, jj, kk, ni, nj, nk + + ii = i; jj = j; kk = k + ni = obj%tPoints(1) - 1; nj = obj%tPoints(2) - 1; nk = obj%tPoints(3) - 1 + + ans = (jj - 1) * ni + ii + ni * (nj + 1) * (kk - 1) + +END FUNCTION mesh_GetEdgeNumberOnAxis1 + +!---------------------------------------------------------------------------- +! GetEdgeNumberOnAxis2 +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetEdgeNumberOnAxis2(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + !! point number + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ii, jj, kk, ni, nj, nk + + ii = i; jj = j; kk = k + ni = obj%tPoints(1) - 1; nj = obj%tPoints(2) - 1; nk = obj%tPoints(3) - 1 + + ans = obj%tEdges1 + (jj - 1) * (ni + 1) + ii + (ni + 1) * nj * (kk - 1) +END FUNCTION mesh_GetEdgeNumberOnAxis2 + +!---------------------------------------------------------------------------- +! GetEdgeNumberOnAxis3 +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetEdgeNumberOnAxis3(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + !! cell number + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ii, jj, kk, ni, nj, nk + + ii = i; jj = j; kk = k + ni = obj%tPoints(1) - 1; nj = obj%tPoints(2) - 1; nk = obj%tPoints(3) - 1 + + ans = obj%tEdges1 + obj%tEdges2 & + & + (jj - 1) * (ni + 1) + ii + (ni + 1) * (nj + 1) * (kk - 1) +END FUNCTION mesh_GetEdgeNumberOnAxis3 + +!---------------------------------------------------------------------------- +! GetSurfaceNumberXY +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetSurfaceNumberXY(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + !! point number + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ii, jj, kk, ni, nj, nk + + ii = i; jj = j; kk = k + ni = obj%tPoints(1) - 1; nj = obj%tPoints(2) - 1; nk = obj%tPoints(3) - 1 + + ans = (jj - 1) * ni + ii + ni * nj * (kk - 1) + +END FUNCTION mesh_GetSurfaceNumberXY + +!---------------------------------------------------------------------------- +! GetSurfaceNumberYZ +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetSurfaceNumberYZ(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + !! point number + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ii, jj, kk, ni, nj, nk + + ii = i; jj = j; kk = k + ni = obj%tPoints(1) - 1; nj = obj%tPoints(2) - 1; nk = obj%tPoints(3) - 1 + + ans = obj%tSurfacesXY + (kk - 1) * nj + jj + nj * nk * (ii - 1) + +END FUNCTION mesh_GetSurfaceNumberYZ + +!---------------------------------------------------------------------------- +! GetSurfaceNumberXZ +!---------------------------------------------------------------------------- + +FUNCTION mesh_GetSurfaceNumberXZ(obj, i, j, k) RESULT(ans) + CLASS(GmshStructuredMesh_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: i, j, k + !! point number + INTEGER(I4B) :: ans + + INTEGER(I4B) :: ii, jj, kk, ni, nj, nk + + ii = i; jj = j; kk = k + ni = obj%tPoints(1) - 1; nj = obj%tPoints(2) - 1; nk = obj%tPoints(3) - 1 + + ans = obj%tSurfacesXY + obj%tSurfacesYZ + & + & (kk - 1) * ni + ii + ni * nk * (jj - 1) + +END FUNCTION mesh_GetSurfaceNumberXZ + +END MODULE GmshStructuredMesh_Class diff --git a/src/modules/GmshAPI/src/Gmsh_Class.F90 b/src/modules/GmshAPI/src/Gmsh_Class.F90 index 098d6edd6..b1e66df68 100644 --- a/src/modules/GmshAPI/src/Gmsh_Class.F90 +++ b/src/modules/GmshAPI/src/Gmsh_Class.F90 @@ -17,7 +17,7 @@ !> authors: Vikas Sharma, Ph. D. ! date: 26 April 2021 -! summary:Gmsh-Fortran Interface +! summary: Gmsh-Fortran Interface MODULE Gmsh_Class USE ISO_C_BINDING @@ -34,7 +34,7 @@ MODULE Gmsh_Class IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "Gmsh_Class" +CHARACTER(*), PARAMETER :: modName = "Gmsh_Class" INTEGER(C_INT) :: ierr !$OMP THREADPRIVATE(ierr) INTEGER(I4B), PARAMETER :: maxStrLen = GMSH_API_MAX_STR_LEN diff --git a/src/modules/TxtFile/src/EnquireMethods.inc b/src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 similarity index 63% rename from src/modules/TxtFile/src/EnquireMethods.inc rename to src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 index 19809751d..0803e0b56 100644 --- a/src/modules/TxtFile/src/EnquireMethods.inc +++ b/src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 @@ -15,18 +15,19 @@ ! along with this program. If not, see ! +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-05 +! summary: This module is used when Gmsh SDK is not used + +MODULE Gmsh_Class +IMPLICIT NONE +END MODULE Gmsh_Class + !---------------------------------------------------------------------------- -! isValidRecord@EnquireMethods +! !---------------------------------------------------------------------------- -INTERFACE -MODULE FUNCTION txt_isValidRecord( obj, aline, ignoreComment, ignoreBlank, & - & commentSymbol ) RESULT( Ans ) - CLASS(TxtFile_), INTENT(IN) :: obj - TYPE(String), INTENT( IN ) :: aline - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - LOGICAL( LGT ) :: ans -END FUNCTION txt_isValidRecord -END INTERFACE +MODULE GmshStructuredGrid_Class +IMPLICIT NONE +END MODULE GmshStructuredGrid_Class + diff --git a/src/modules/LinSolver/src/LinSolver_Class.F90 b/src/modules/LinSolver/src/LinSolver_Class.F90 index 8de690c61..605ffb065 100644 --- a/src/modules/LinSolver/src/LinSolver_Class.F90 +++ b/src/modules/LinSolver/src/LinSolver_Class.F90 @@ -21,7 +21,7 @@ MODULE LinSolver_Class USE GlobalData -USE BaseType +USE Basetype USE String_Class, ONLY: String USE FPL, ONLY: ParameterList_ USE ExceptionHandler_Class, ONLY: e @@ -31,8 +31,14 @@ MODULE LinSolver_Class USE HDF5File_Class IMPLICIT NONE PRIVATE +PUBLIC :: LinSolverInitiate +PUBLIC :: LinSolverDisplay +PUBLIC :: LinSolverDeallocate +PUBLIC :: LinSolverCheckEssentialParam +PUBLIC :: LinSolverPointer_ +PUBLIC :: LinSolver_ -CHARACTER(*), PARAMETER :: modName = "Linsolver_Class" +CHARACTER(*), PARAMETER :: modName = "LinSolver_Class" CHARACTER(*), PARAMETER :: myprefix = "LinSolver" CHARACTER(*), PARAMETER :: myengine = "NATIVE_SERIAL" INTEGER(I4B), PARAMETER :: IPAR_LENGTH = 14 @@ -83,13 +89,12 @@ MODULE LinSolver_Class PROCEDURE, PUBLIC, PASS(obj) :: Solve => ls_solve !! Solve the system of linear equation PROCEDURE, PUBLIC, NOPASS :: & - & getLinSolverCodeFromName => ls_getLinSolverCodeFromName + & GetLinSolverCodeFromName => ls_GetLinSolverCodeFromName PROCEDURE, PUBLIC, NOPASS :: & - & getLinSolverNameFromCode => ls_getLinSolverNameFromCode + & GetLinSolverNameFromCode => ls_GetLinSolverNameFromCode + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => ls_GetPrefix END TYPE LinSolver_ -PUBLIC :: LinSolver_ - !---------------------------------------------------------------------------- ! TypeLinSolver !---------------------------------------------------------------------------- @@ -104,10 +109,8 @@ MODULE LinSolver_Class CLASS(LinSolver_), POINTER :: Ptr => NULL() END TYPE LinSolverPointer_ -PUBLIC :: LinSolverPointer_ - !---------------------------------------------------------------------------- -! getLinSolverCodeFromName@GetMethods +! GetLinSolverCodeFromName@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -115,14 +118,14 @@ MODULE LinSolver_Class ! summary: Get linear solver integer code from name INTERFACE - MODULE PURE FUNCTION ls_getLinSolverCodeFromName(name) RESULT(Ans) + MODULE PURE FUNCTION ls_GetLinSolverCodeFromName(name) RESULT(Ans) CHARACTER(*), INTENT(IN) :: name INTEGER(I4B) :: ans - END FUNCTION ls_getLinSolverCodeFromName + END FUNCTION ls_GetLinSolverCodeFromName END INTERFACE !---------------------------------------------------------------------------- -! getLinSolverNameFromCode@GetMethods +! GetLinSolverNameFromCode@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -130,148 +133,29 @@ END FUNCTION ls_getLinSolverCodeFromName ! summary: Get the linear solver name from integer code INTERFACE - MODULE PURE FUNCTION ls_getLinSolverNameFromCode(name) RESULT(Ans) + MODULE PURE FUNCTION ls_GetLinSolverNameFromCode(name) RESULT(Ans) INTEGER(I4B), INTENT(IN) :: name CHARACTER(15) :: ans - END FUNCTION ls_getLinSolverNameFromCode + END FUNCTION ls_GetLinSolverNameFromCode END INTERFACE !---------------------------------------------------------------------------- -! setLinSolverParam@SetMethods +! GetPrefix@GetMethods !---------------------------------------------------------------------------- -!> authors: Vikas Sharma, Ph. D. -! date: 25 Aug 2021 -! summary: Set linear solver parameters +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-09 +! summary: Get the prefix INTERFACE - MODULE SUBROUTINE setLinSolverParam( & - & param, & - & solverName, & - & preconditionOption, & - & convergenceIn, & - & convergenceType, & - & maxIter, & - & relativeToRHS, & - & KrylovSubspaceSize, & - & rtol, & - & atol, & - & scale, & - & initx_zeros, & - & bicgstab_ell, & - & sor_omega, & - & p_name, & - & p_ilu_lfil, & - & p_ilu_mbloc, & - & p_ilu_droptol, & - & p_ilu_permtol, & - & p_ilu_alpha, & - & p_ilu_fill, & - & p_ssor_omega, & - & p_hybrid_i, & - & p_hybrid_maxiter, & - & p_hybrid_tol, & - & p_hybrid_omega, & - & p_hybrid_ell, & - & p_hybrid_restart, & - & p_is_alpha, & - & p_is_m, & - & p_sainv_drop, & - & p_saamg_unsym, & - & p_saamg_theta, & - & p_iluc_drop, & - & p_iluc_rate, & - & p_adds, & - & p_adds_iter & - & ) - TYPE(ParameterList_), INTENT(INOUT) :: param - INTEGER(I4B), OPTIONAL, INTENT(IN) :: solverName - !! Solver name - INTEGER(I4B), OPTIONAL, INTENT(IN) :: preconditionOption - !! precondition option - INTEGER(I4B), OPTIONAL, INTENT(IN) :: convergenceIn - !! convergenceInRes - !! convergenceInSol - INTEGER(I4B), OPTIONAL, INTENT(IN) :: convergenceType - !! relativeConvergence - !! absoluteConvergence - INTEGER(I4B), OPTIONAL, INTENT(IN) :: maxIter - !! maximum iteration - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: relativeToRHS - !! relative to RHS - INTEGER(I4B), OPTIONAL, INTENT(IN) :: KrylovSubspaceSize - !! KrylovSubspaceSize - REAL(DFP), OPTIONAL, INTENT(IN) :: rtol - !! relative tolerance - REAL(DFP), OPTIONAL, INTENT(IN) :: atol - !! absolute tolerance - INTEGER(I4B), OPTIONAL, INTENT(IN) :: scale - !! LIS, Solver digonal scaling - !! scale_none: No scaling - !! scale_jacobi: jacobi scaling inv(D)Ax = inv(D)b - !! scale_symm_diag: sqrt(inv(D)) A sqrt(inv(D)) x = sqrt(inv(D))b - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: initx_zeros - !! if True, then we set sol=0.0 as initial guess. - INTEGER(I4B), OPTIONAL, INTENT(IN) :: bicgstab_ell - !! Needed for solver BiCGSTABL - REAL(DFP), OPTIONAL, INTENT(IN) :: sor_omega - !! The relaxation coefficient - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_name - !! Name of preconditioner - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_lfil - !! Sparsekit, ilu - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_mbloc - !! Sparsekit, ilu - REAL(DFP), OPTIONAL, INTENT(IN) :: p_ilu_droptol - !! Sparsekit, ilu - REAL(DFP), OPTIONAL, INTENT(IN) :: p_ilu_permtol - !! Sparsekit, ilu - REAL(DFP), OPTIONAL, INTENT(IN) :: p_ilu_alpha - !! Sparsekit, ilu, alpha - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_ilu_fill - !! ILU, fill-in - REAL(DFP), OPTIONAL, INTENT(IN) :: p_ssor_omega - !! The relaxation coefficient omega in (0.0, 2.0) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_i - !! Hybrid, the linear solver, for example, SSOR, GMRES, - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_maxiter - !! Hybrid, maximum number of iterations - REAL(DFP), OPTIONAL, INTENT(IN) :: p_hybrid_tol - !! Hybrid, convergence tolerance - REAL(DFP), OPTIONAL, INTENT(IN) :: p_hybrid_omega - !! Hybrid, The relaxation coefficient omega of the SOR - !! omega should be in (0.0, 2.0) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_ell - !!Hybrid, The degree l of the BiCGSTAB(l) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_hybrid_restart - !! Hybrid, The restart value of GMRES and Orthomin - REAL(DFP), OPTIONAL, INTENT(IN) :: p_is_alpha - !! I+S, The parameter alpha of $I + \alpha {S}^{m}$ - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_is_m - !! I+S, The parameter m of $I + \alpha {S}^{m}$ - REAL(DFP), OPTIONAL, INTENT(IN) :: p_sainv_drop - !! SA-AMG, The drop criteria - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: p_saamg_unsym - !! SA-AMG, Select the unsymmetric version - !! The matrix structure must be symmetric - REAL(DFP), OPTIONAL, INTENT(IN) :: p_saamg_theta - !! SA-AMG, The drop criteria - REAL(DFP), OPTIONAL, INTENT(IN) :: p_iluc_drop - !! Crout ILU, default is 0.05, The drop criteria - REAL(DFP), OPTIONAL, INTENT(IN) :: p_iluc_rate - !! Crout ILU, The ratio of the maximum fill-in - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: p_adds - !! ilut Additive Schwarz, default is true - INTEGER(I4B), OPTIONAL, INTENT(IN) :: p_adds_iter - !! default value is 1 - !! ILUT Additive Schwarz number of iteration - END SUBROUTINE setLinSolverParam + MODULE FUNCTION ls_GetPrefix(obj) RESULT(ans) + CLASS(LinSolver_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION ls_GetPrefix END INTERFACE -PUBLIC :: setLinSolverParam - !---------------------------------------------------------------------------- -! getLinSolverParam@GetMethods +! GetLinSolverParam@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -279,7 +163,7 @@ END SUBROUTINE setLinSolverParam ! summary: Returns the linear solver parameters INTERFACE - MODULE SUBROUTINE getLinSolverParam( & + MODULE SUBROUTINE GetLinSolverParam( & & param, & & solverName, & & preconditionOption, & @@ -334,7 +218,7 @@ MODULE SUBROUTINE getLinSolverParam( & !! scale_jacobi: jacobi scaling inv(D)Ax = inv(D)b !! scale_symm_diag: sqrt(inv(D)) A sqrt(inv(D)) x = sqrt(inv(D))b LOGICAL(LGT), OPTIONAL, INTENT(OUT) :: initx_zeros - !! if True, then we set sol=0.0 as initial guess. + !! if True, then we Set sol=0.0 as initial guess. INTEGER(I4B), OPTIONAL, INTENT(OUT) :: bicgstab_ell !! Needed for solver BiCGSTABL REAL(DFP), OPTIONAL, INTENT(OUT) :: sor_omega @@ -388,7 +272,7 @@ MODULE SUBROUTINE getLinSolverParam( & INTEGER(I4B), OPTIONAL, INTENT(OUT) :: p_adds_iter !! default value is 1 !! ILUT Additive Schwarz number of iteration - END SUBROUTINE getLinSolverParam + END SUBROUTINE GetLinSolverParam END INTERFACE !---------------------------------------------------------------------------- @@ -399,22 +283,16 @@ END SUBROUTINE getLinSolverParam ! date: 25 Aug 2021 ! summary: This routine checks the essential parameters -INTERFACE +INTERFACE LinSolverCheckEssentialParam MODULE SUBROUTINE ls_checkEssentialParam(obj, param) CLASS(LinSolver_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param END SUBROUTINE ls_checkEssentialParam -END INTERFACE - -INTERFACE LinSolverCheckEssentialParam - MODULE PROCEDURE ls_checkEssentialParam END INTERFACE LinSolverCheckEssentialParam -PUBLIC :: LinSolverCheckEssentialParam - -!----------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!----------------------------------------------------------------------------- +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 16 July 2021 @@ -424,26 +302,20 @@ END SUBROUTINE ls_checkEssentialParam ! ! This subroutine initiate the [[LinSolver_]] object ! -! - It sets the name of the solver -! - It sets the parameters related to the solver +! - It Sets the name of the solver +! - It Sets the parameters related to the solver ! ! If name of the solver is `lis_gmres`, `lis_fgmres`, `lis_dqgmres`, ! or `lis_om` then `ipar(1)` denotes the number of restarts required in -! these algorithms. Default value is set to 20. +! these algorithms. Default value is Set to 20. -INTERFACE +INTERFACE LinSolverInitiate MODULE SUBROUTINE ls_Initiate(obj, param) CLASS(LinSolver_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param END SUBROUTINE ls_Initiate -END INTERFACE - -INTERFACE LinSolverInitiate - MODULE PROCEDURE ls_Initiate END INTERFACE LinSolverInitiate -PUBLIC :: LinSolverInitiate - !---------------------------------------------------------------------------- ! Set@SetMethods !---------------------------------------------------------------------------- @@ -479,20 +351,14 @@ END SUBROUTINE ls_Solve ! Display@IOMethods !---------------------------------------------------------------------------- -INTERFACE +INTERFACE LinSolverDisplay MODULE SUBROUTINE ls_Display(obj, msg, unitno) CLASS(LinSolver_), INTENT(IN) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: Unitno END SUBROUTINE ls_Display -END INTERFACE - -INTERFACE LinSolverDisplay - MODULE PROCEDURE ls_Display END INTERFACE LinSolverDisplay -PUBLIC :: LinSolverDisplay - !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- @@ -513,18 +379,12 @@ END SUBROUTINE ls_Import ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- -INTERFACE +INTERFACE LinSolverDeallocate MODULE SUBROUTINE ls_Deallocate(obj) CLASS(LinSolver_), INTENT(INOUT) :: obj END SUBROUTINE ls_Deallocate -END INTERFACE - -INTERFACE LinSolverDeallocate - MODULE PROCEDURE ls_Deallocate END INTERFACE LinSolverDeallocate -PUBLIC :: LinSolverDeallocate - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- diff --git a/src/modules/MSHFile/src/MSHFile_Class.F90 b/src/modules/MSHFile/src/MSHFile_Class.F90 index c938a5c08..41badb696 100644 --- a/src/modules/MSHFile/src/MSHFile_Class.F90 +++ b/src/modules/MSHFile/src/MSHFile_Class.F90 @@ -13,7 +13,6 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see -! MODULE MSHFile_Class USE BaseType @@ -23,13 +22,16 @@ MODULE MSHFile_Class USE ExceptionHandler_Class, ONLY: e USE mshFormat_Class USE mshPhysicalNames_Class -USE mshEntity_Class, only: mshEntity_, TypeMshEntity +USE mshEntity_Class, ONLY: mshEntity_, TypeMshEntity USE mshNodes_Class USE mshElements_Class USE HDF5File_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "MSHFile_CLASS" +PUBLIC :: DEALLOCATE +PUBLIC :: MSHPointer_ +PUBLIC :: MSHFile_ !---------------------------------------------------------------------------- ! MSHFile_ @@ -98,8 +100,6 @@ MODULE MSHFile_Class ! !---------------------------------------------------------------------------- -PUBLIC :: MSHFile_ - ! TYPE( MSHFile_ ), PUBLIC, PARAMETER :: TypeMSH = MSHFile_( ) !---------------------------------------------------------------------------- @@ -110,8 +110,6 @@ MODULE MSHFile_Class CLASS(MSHFile_), POINTER :: Ptr => NULL() END TYPE MSHPointer_ -PUBLIC :: MSHPointer_ - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -130,19 +128,13 @@ END SUBROUTINE msh_Final ! date: 11 June 2021 ! summary: This will deallocate data -INTERFACE +INTERFACE DEALLOCATE MODULE SUBROUTINE msh_Deallocate(obj, Delete) CLASS(MSHFile_), INTENT(INOUT) :: obj LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete END SUBROUTINE msh_Deallocate -END INTERFACE - -INTERFACE DEALLOCATE - MODULE PROCEDURE msh_Deallocate END INTERFACE DEALLOCATE -PUBLIC :: DEALLOCATE - !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- diff --git a/src/modules/MatrixField/src/MatrixField_Class.F90 b/src/modules/MatrixField/src/MatrixField_Class.F90 index 6ec7e1029..66abeeddd 100644 --- a/src/modules/MatrixField/src/MatrixField_Class.F90 +++ b/src/modules/MatrixField/src/MatrixField_Class.F90 @@ -111,7 +111,7 @@ MODULE MatrixField_Class ! date: 15 July 2021 ! summary: This is native implementation of finite element tangent matrices. ! -!{!pages/MatrixField_.md!} +!{!pages/docs-api/MatrixField/MatrixField_.md!} TYPE, EXTENDS(AbstractMatrixField_) :: MatrixField_ LOGICAL(LGT) :: isRectangle = .FALSE. diff --git a/src/modules/Mesh/src/Mesh_Class.F90 b/src/modules/Mesh/src/Mesh_Class.F90 index 610a16cd4..71a41539b 100755 --- a/src/modules/Mesh/src/Mesh_Class.F90 +++ b/src/modules/Mesh/src/Mesh_Class.F90 @@ -306,7 +306,7 @@ MODULE Mesh_Class TYPE(ElemshapeData_), PUBLIC :: spaceElemSD !! Element shape data on space element TYPE(STElemshapeData_), ALLOCATABLE, PUBLIC :: stelemsd(:) - !! Element shape data on space element + !! Element shape data on space-time element TYPE(String) :: quadTypeForSpace !! quadrature type for space TYPE(String) :: continuityTypeForSpace @@ -2609,7 +2609,7 @@ END SUBROUTINE mesh_SetQuality ! !# Introduction ! -! This routine Set the local shape data in space (linSpaceElemSD and +! This routine sets the local shape data in space (linSpaceElemSD and ! spaceElemSD) for the mesh. It also creates the quadrature points in space. INTERFACE diff --git a/src/modules/MeshSelection/src/MeshSelection.toml b/src/modules/MeshSelection/src/MeshSelection.toml new file mode 100644 index 000000000..bb32e1aab --- /dev/null +++ b/src/modules/MeshSelection/src/MeshSelection.toml @@ -0,0 +1,44 @@ +[region] +isSelectionByMeshID = false +isSelectionByElemNum = false +isSelectionByBox = false +isSelectionByNodeNum = false + +[region.meshID] +point = [1,2,3] # "filename.txt" +line = [1,2,3,4] # "filename.txt" +surface = [1,2,3] # "filename.txt" +volume = [1,2,3] # "filename.txt" + +[region.box] +point = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +line = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +surface = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +volume = [ +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, +{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} +] + +[region.elemNum] +point = [1,2,3] +line = [1,2,3] +surface=[1,2,3] +volume=[1,2,3] + +[region.nodeNum] +point = [1,2,3] +line = [1,2,3] +surface=[1,2,3] +volume=[1,2,3] diff --git a/src/modules/MeshSelection/src/MeshSelection_Class.F90 b/src/modules/MeshSelection/src/MeshSelection_Class.F90 index 43d7bd15e..3acca4215 100644 --- a/src/modules/MeshSelection/src/MeshSelection_Class.F90 +++ b/src/modules/MeshSelection/src/MeshSelection_Class.F90 @@ -25,12 +25,19 @@ MODULE MeshSelection_Class USE ExceptionHandler_Class, ONLY: e USE HDF5File_Class, ONLY: HDF5File_ USE Domain_Class, ONLY: Domain_ +USE FPL, ONLY: ParameterList_ +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "MeshSelection_Class" +CHARACTER(*), PARAMETER :: myprefix = "MeshSelection" PUBLIC :: DEALLOCATE PUBLIC :: MeshSelection_ PUBLIC :: MeshSelectionPointer_ +PUBLIC :: MeshSelectionImportParamFromToml +PUBLIC :: MeshSelectionImportFromToml +PUBLIC :: SetMeshSelectionParam !---------------------------------------------------------------------------- ! MeshSelection_ @@ -68,23 +75,49 @@ MODULE MeshSelection_Class !! Element number in mesh of surfaces TYPE(IntVector_) :: volumeElemNum !! Element number in mesh of volume + TYPE(IntVector_) :: pointNodeNum + !! Global Node numbers in pointEntity + !! INFO: Currently, we are not using this (futuristic) + TYPE(IntVector_) :: curveNodeNum + !! Global Node numbers in cuveEntity + !! INFO: Currently, we are not using this (futuristic) + TYPE(IntVector_) :: surfaceNodeNum + !! Global Node numbers in surfaceEntity + !! INFO: Currently, we are not using this (futuristic) + TYPE(IntVector_) :: volumeNodeNum + !! Global Node numbers in volumeEntity + !! INFO: Currently, we are not using this (futuristic) TYPE(IntVector_) :: nodeNum !! Global Node numbers - !! TODO: add BoundingBox to MeshSelection_ - !! type(BoundingBoxPointer_), allocatable :: bbox(:) - !! Accordingly, modify the initiate method. + TYPE(BoundingBox_), ALLOCATABLE :: pointBox(:) + !! boxes for point + TYPE(BoundingBox_), ALLOCATABLE :: curveBox(:) + !! boxes for line + TYPE(BoundingBox_), ALLOCATABLE :: surfaceBox(:) + !! boxes for surface + TYPE(BoundingBox_), ALLOCATABLE :: volumeBox(:) + !! boxes for volume + CONTAINS + PRIVATE + ! CONSTRUCTOR: ! @ConstructorMethods - PROCEDURE, PUBLIC, PASS(obj) :: Initiate => meshSelect_Initiate - !! Initiates an instance of MeshSelection_ + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & meshSelect_CheckEssentialParam + !! Check essential parameter + PROCEDURE, PASS(obj) :: Initiate1 => meshSelect_Initiate1 + !! Initiate an instance of meshSelection + PROCEDURE, PASS(obj) :: Initiate2 => meshSelect_Initiate2 + !! Initiate an instance of meshSelection + GENERIC, PUBLIC :: Initiate => Initiate1, Initiate2 + !! Initiate an instance of meshSelection PROCEDURE, PASS(obj) :: Copy => meshSelect_Copy !! This routine copies object GENERIC, PUBLIC :: ASSIGNMENT(=) => Copy !! Assignment operator - PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => & - & meshSelect_Deallocate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => meshSelect_Deallocate !! Deallocate Data FINAL :: meshSelect_Final @@ -95,15 +128,30 @@ MODULE MeshSelection_Class PROCEDURE, PUBLIC, PASS(obj) :: Set => meshSelect_Set !! This routine should be called when we are done !! setting the regions in the instance + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => meshSelect_Import !! Import from the hdf5 file PROCEDURE, PUBLIC, PASS(obj) :: Export => meshSelect_Export !! Export to the HDF5File PROCEDURE, PUBLIC, PASS(obj) :: Display => meshSelect_Display !! Displays the content + PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & + & meshSelect_ImportParamFromToml + PROCEDURE, PASS(obj) :: ImportFromToml1 => & + & meshSelect_ImportFromToml1 + PROCEDURE, PASS(obj) :: ImportFromToml2 => & + & meshSelect_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromToml => & + & ImportFromToml1, ImportFromToml2 + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => meshSelect_getMeshID !! Returns the mesh id if available PROCEDURE, PASS(obj) :: meshSelect_GetElemNum1 + !! Returns the element numbers if available PROCEDURE, PASS(obj) :: meshSelect_GetElemNum2 !! Returns the element numbers if available @@ -138,6 +186,7 @@ MODULE MeshSelection_Class !! Query the mesh selection PROCEDURE, PUBLIC, PASS(obj) :: GetParam => meshSelect_GetQuery !! Query the mesh selection + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => meshSelect_GetPrefix END TYPE MeshSelection_ !---------------------------------------------------------------------------- @@ -182,18 +231,56 @@ MODULE SUBROUTINE Deallocate_Ptr_Vector(obj) END SUBROUTINE Deallocate_Ptr_Vector END INTERFACE DEALLOCATE +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Check essential parameter + +INTERFACE + MODULE SUBROUTINE meshSelect_CheckEssentialParam(obj, param, prefix) + CLASS(MeshSelection_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE meshSelect_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! SetMeshSelectionParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Set mesh parameters + +INTERFACE + MODULE SUBROUTINE SetMeshSelectionParam(param, & + & prefix, & + & isSelectionByMeshID, & + & isSelectionByElemNum, & + & isSelectionByBox, & + & isSelectionByNodeNum) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: prefix + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByMeshID + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByElemNum + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByBox + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByNodeNum + END SUBROUTINE SetMeshSelectionParam +END INTERFACE + !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 28 Aug 2021 -! summary: Initiate an instance of [[MeshSelection_]] -! -! TODO Initiate by passing ParameterList object to initiate. +! summary: Initiate an instance of meshSelection (Deprecated) INTERFACE - MODULE SUBROUTINE meshSelect_Initiate( & + MODULE SUBROUTINE meshSelect_Initiate1( & & obj, & & isSelectionByMeshID, & & isSelectionByElemNum, & @@ -204,7 +291,22 @@ MODULE SUBROUTINE meshSelect_Initiate( & LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByElemNum LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByBox LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isSelectionByNodeNum - END SUBROUTINE meshSelect_Initiate + END SUBROUTINE meshSelect_Initiate1 +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 28 Aug 2021 +! summary: Initiate an instance of MeshSelection_ + +INTERFACE + MODULE SUBROUTINE meshSelect_Initiate2(obj, param) + CLASS(MeshSelection_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + END SUBROUTINE meshSelect_Initiate2 END INTERFACE !---------------------------------------------------------------------------- @@ -213,7 +315,7 @@ END SUBROUTINE meshSelect_Initiate !> authors: Vikas Sharma, Ph. D. ! date: 1 Sep 2021 -! summary: Initiate an instance of [[MeshSelection_]] by copying other object +! summary: Initiate an instance of MeshSelection_ by copying other object INTERFACE MODULE SUBROUTINE meshSelect_Copy(obj, obj2) @@ -265,7 +367,8 @@ MODULE SUBROUTINE meshSelect_Add(obj, dom, dim, meshID, box, elemNum, & TYPE(Domain_), OPTIONAL, INTENT(IN) :: dom INTEGER(I4B), OPTIONAL, INTENT(IN) :: dim INTEGER(I4B), OPTIONAL, INTENT(IN) :: meshID(:) - TYPE(BoundingBox_), OPTIONAL, INTENT(IN) :: box + TYPE(BoundingBox_), OPTIONAL, INTENT(IN) :: box(:) + !! boxes INTEGER(I4B), OPTIONAL, INTENT(IN) :: elemNum(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: nodeNum(:) END SUBROUTINE meshSelect_Add @@ -302,6 +405,58 @@ MODULE SUBROUTINE meshSelect_Import(obj, hdf5, group, dom) END SUBROUTINE meshSelect_Import END INTERFACE +!---------------------------------------------------------------------------- +! ImportParamFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param by reading the toml table + +INTERFACE MeshSelectionImportParamFromToml + MODULE SUBROUTINE meshSelect_ImportParamFromToml(obj, param, table) + CLASS(MeshSelection_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE meshSelect_ImportParamFromToml +END INTERFACE MeshSelectionImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE MeshSelectionImportFromToml + MODULE SUBROUTINE meshSelect_ImportFromToml1(obj, table, dom) + CLASS(MeshSelection_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + TYPE(Domain_), OPTIONAL, INTENT(IN) :: dom + END SUBROUTINE meshSelect_ImportFromToml1 +END INTERFACE MeshSelectionImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE MeshSelectionImportFromToml + MODULE SUBROUTINE meshSelect_ImportFromToml2(obj, tomlName, afile, & + & filename, printToml, dom) + CLASS(MeshSelection_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + TYPE(Domain_), OPTIONAL, INTENT(IN) :: dom + END SUBROUTINE meshSelect_ImportFromToml2 +END INTERFACE MeshSelectionImportFromToml + !---------------------------------------------------------------------------- ! Export@IOMethods !---------------------------------------------------------------------------- @@ -359,11 +514,11 @@ END FUNCTION meshSelect_GetMeshID ! summary: This routine returns true if meshID of given dim is allocated INTERFACE - MODULE PURE FUNCTION meshSelect_isMeshIDAllocated(obj, dim) RESULT(Ans) + MODULE PURE FUNCTION meshSelect_IsMeshIDAllocated(obj, dim) RESULT(Ans) CLASS(MeshSelection_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: dim LOGICAL(LGT) :: ans - END FUNCTION meshSelect_isMeshIDAllocated + END FUNCTION meshSelect_IsMeshIDAllocated END INTERFACE !---------------------------------------------------------------------------- @@ -375,11 +530,11 @@ END FUNCTION meshSelect_isMeshIDAllocated ! summary: This routine returns MeshID INTERFACE - MODULE PURE FUNCTION meshSelect_isElemNumAllocated(obj, dim) RESULT(Ans) + MODULE PURE FUNCTION meshSelect_IsElemNumAllocated(obj, dim) RESULT(Ans) CLASS(MeshSelection_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: dim LOGICAL(LGT) :: ans - END FUNCTION meshSelect_isElemNumAllocated + END FUNCTION meshSelect_IsElemNumAllocated END INTERFACE !---------------------------------------------------------------------------- @@ -391,10 +546,10 @@ END FUNCTION meshSelect_isElemNumAllocated ! summary: This routine returns true if node numbers are allocated INTERFACE - MODULE PURE FUNCTION meshSelect_isNodeNumAllocated(obj) RESULT(Ans) + MODULE PURE FUNCTION meshSelect_IsNodeNumAllocated(obj) RESULT(Ans) CLASS(MeshSelection_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION meshSelect_isNodeNumAllocated + END FUNCTION meshSelect_IsNodeNumAllocated END INTERFACE !---------------------------------------------------------------------------- @@ -555,4 +710,19 @@ MODULE FUNCTION meshSelect_GetNodeNum3(obj, domain) RESULT(Ans) END FUNCTION meshSelect_GetNodeNum3 END INTERFACE +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-15 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION meshSelect_GetPrefix(obj) RESULT(ans) + CLASS(MeshSelection_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION meshSelect_GetPrefix +END INTERFACE + END MODULE MeshSelection_Class diff --git a/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 b/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 index 146e84032..b228ab1c1 100644 --- a/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 +++ b/src/modules/MixedFiniteElement/src/MixedFiniteElement_Class.F90 @@ -43,6 +43,7 @@ MODULE MixedFiniteElement_Class !{!pages/docs-api/MixedFiniteElement/MixedFiniteElement_.md!} TYPE, EXTENDS(AbstractFE_) :: MixedFiniteElement_ + PRIVATE TYPE(FiniteElementPointer_), ALLOCATABLE :: fe(:) CONTAINS PRIVATE diff --git a/src/modules/NeumannBC/src/NeumannBC_Class.F90 b/src/modules/NeumannBC/src/NeumannBC_Class.F90 index 932ac0bc2..2e7b3332c 100644 --- a/src/modules/NeumannBC/src/NeumannBC_Class.F90 +++ b/src/modules/NeumannBC/src/NeumannBC_Class.F90 @@ -24,16 +24,18 @@ MODULE NeumannBC_Class USE FPL, ONLY: ParameterList_ USE AbstractBC_Class USE DirichletBC_Class +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "NeumannBC_CLASS" CHARACTER(*), PARAMETER :: myprefix = "NeumannBC" PUBLIC :: NeumannBC_ PUBLIC :: NeumannBCPointer_ -PUBLIC :: SetNeumannBCParam PUBLIC :: DEALLOCATE PUBLIC :: AddNeumannBC PUBLIC :: GetNeumannBCPointer +PUBLIC :: NeumannBCImportFromToml !---------------------------------------------------------------------------- ! NeumannBC_ @@ -46,9 +48,7 @@ MODULE NeumannBC_Class TYPE, EXTENDS(DirichletBC_) :: NeumannBC_ CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & - & bc_checkEssentialParam - PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix FINAL :: bc_Final END TYPE NeumannBC_ @@ -88,55 +88,6 @@ MODULE SUBROUTINE bc_Deallocate_Ptr_Vector(obj) END SUBROUTINE bc_Deallocate_Ptr_Vector END INTERFACE DEALLOCATE -!---------------------------------------------------------------------------- -! checkEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 4 Feb 2022 -! summary: Check essential parameters - -INTERFACE - MODULE SUBROUTINE bc_CheckEssentialParam(obj, param) - CLASS(NeumannBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE bc_CheckEssentialParam -END INTERFACE - -!---------------------------------------------------------------------------- -! setDirichletParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE SetNeumannBCParam(param, name, idof, nodalValueType, & - & useFunction, isNormal, isTangent) - TYPE(ParameterList_), INTENT(INOUT) :: param - CHARACTER(*), INTENT(IN) :: name - INTEGER(I4B), INTENT(IN) :: idof - INTEGER(I4B), INTENT(IN) :: nodalValueType - !! Space - !! Time - !! SpaceTime - !! Constant - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTangent - END SUBROUTINE SetNeumannBCParam -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) - CLASS(NeumannBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(MeshSelection_), INTENT(IN) :: boundary - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -188,4 +139,59 @@ MODULE FUNCTION bc_GetNeumannBCPointer(nbc, nbcNo) RESULT(ans) END FUNCTION bc_GetNeumannBCPointer END INTERFACE GetNeumannBCPointer +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: This function returns the prefix + +INTERFACE + MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) + CLASS(NeumannBC_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bc_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE NeumannBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom, tomlName) + TYPE(NeumannBCPointer_), INTENT(INOUT) :: obj(:) + !! Should be allocated outside + TYPE(toml_table), INTENT(INOUT) :: table + !! Toml table to returned + CLASS(Domain_), TARGET, INTENT(IN) :: dom + !! domain + CHARACTER(*), INTENT(IN) :: tomlName + END SUBROUTINE bc_ImportFromToml1 +END INTERFACE NeumannBCImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE NeumannBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & + & filename, printToml) + TYPE(NeumannBCPointer_), INTENT(INOUT) :: obj(:) + CLASS(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE bc_ImportFromToml2 +END INTERFACE NeumannBCImportFromToml + END MODULE NeumannBC_Class diff --git a/src/modules/NitscheBC/src/NitscheBC_Class.F90 b/src/modules/NitscheBC/src/NitscheBC_Class.F90 index a012df0cf..1b955b61b 100644 --- a/src/modules/NitscheBC/src/NitscheBC_Class.F90 +++ b/src/modules/NitscheBC/src/NitscheBC_Class.F90 @@ -25,7 +25,9 @@ MODULE NitscheBC_Class USE AbstractBC_Class USE NeumannBC_Class USE DomainConnectivity_Class, ONLY: DomainConnectivity_, & -& DomainConnectivityPointer_ + & DomainConnectivityPointer_ +USE tomlf, ONLY: toml_table +USE TxtFile_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "NitscheBC_Class" @@ -35,6 +37,7 @@ MODULE NitscheBC_Class PUBLIC :: NitscheBC_ PUBLIC :: AddNitscheBC PUBLIC :: GetNitscheBCPointer +PUBLIC :: NitscheBCImportFromToml !---------------------------------------------------------------------------- ! NitscheBC_ @@ -50,18 +53,16 @@ MODULE NitscheBC_Class INTEGER(I4B), ALLOCATABLE :: cellEntity(:) CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & - & bc_checkEssentialParam - PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate PROCEDURE, PUBLIC, PASS(obj) :: SetCellData => bc_SetCellData PROCEDURE, PUBLIC, PASS(obj) :: GetMinCellEntity => bc_GetMinCellEntity PROCEDURE, PUBLIC, PASS(obj) :: GetMaxCellEntity => bc_GetMaxCellEntity - PROCEDURE, PUBLIC, PASS(obj) :: isCellEntityPresent & - & => bc_isCellEntityPresent - PROCEDURE, PUBLIC, PASS(obj) :: getStartIndex => bc_getStartIndex - PROCEDURE, PUBLIC, PASS(obj) :: getEndIndex => bc_getEndIndex - PROCEDURE, PUBLIC, PASS(obj) :: getCellElem => bc_getCellElem - PROCEDURE, PUBLIC, PASS(obj) :: getLocalFacetID => bc_getLocalFacetID + PROCEDURE, PUBLIC, PASS(obj) :: IsCellEntityPresent & + & => bc_IsCellEntityPresent + PROCEDURE, PUBLIC, PASS(obj) :: GetStartIndex => bc_GetStartIndex + PROCEDURE, PUBLIC, PASS(obj) :: GetEndIndex => bc_GetEndIndex + PROCEDURE, PUBLIC, PASS(obj) :: GetCellElem => bc_GetCellElem + PROCEDURE, PUBLIC, PASS(obj) :: GetLocalFacetID => bc_GetLocalFacetID + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix FINAL :: bc_Final END TYPE NitscheBC_ @@ -101,58 +102,6 @@ MODULE SUBROUTINE bc_Deallocate_Ptr_Vector(obj) END SUBROUTINE bc_Deallocate_Ptr_Vector END INTERFACE DEALLOCATE -!---------------------------------------------------------------------------- -! checkEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 4 Feb 2022 -! summary: Check essential parameters - -INTERFACE - MODULE SUBROUTINE bc_checkEssentialParam(obj, param) - CLASS(NitscheBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE bc_checkEssentialParam -END INTERFACE - -!---------------------------------------------------------------------------- -! setNitscheBCParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE setNitscheBCParam(param, name, idof, nodalValueType, & - & useFunction, isNormal, isTangent, useExternal) - TYPE(ParameterList_), INTENT(INOUT) :: param - CHARACTER(*), INTENT(IN) :: name - INTEGER(I4B), INTENT(IN) :: idof - INTEGER(I4B), INTENT(IN) :: nodalValueType - !! Space - !! Time - !! SpaceTime - !! Constant - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTangent - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useExternal - END SUBROUTINE setNitscheBCParam -END INTERFACE - -PUBLIC :: setNitscheBCParam - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE bc_Initiate(obj, param, boundary, dom) - CLASS(NitscheBC_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(MeshSelection_), INTENT(IN) :: boundary - CLASS(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE bc_Initiate -END INTERFACE - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -189,6 +138,10 @@ MODULE PURE FUNCTION bc_GetMinCellEntity(obj) RESULT(ans) END FUNCTION bc_GetMinCellEntity END INTERFACE +!---------------------------------------------------------------------------- +! GetMaxCellEntity@GetMethods +!---------------------------------------------------------------------------- + INTERFACE MODULE PURE FUNCTION bc_GetMaxCellEntity(obj) RESULT(ans) CLASS(NitscheBC_), INTENT(IN) :: obj @@ -196,12 +149,16 @@ MODULE PURE FUNCTION bc_GetMaxCellEntity(obj) RESULT(ans) END FUNCTION bc_GetMaxCellEntity END INTERFACE +!---------------------------------------------------------------------------- +! IsCellEntityPresent@GetMethods +!---------------------------------------------------------------------------- + INTERFACE - MODULE PURE FUNCTION bc_isCellEntityPresent(obj, entityNum) RESULT(ans) + MODULE PURE FUNCTION bc_IsCellEntityPresent(obj, entityNum) RESULT(ans) CLASS(NitscheBC_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: entityNum LOGICAL(LGT) :: ans - END FUNCTION bc_isCellEntityPresent + END FUNCTION bc_IsCellEntityPresent END INTERFACE !---------------------------------------------------------------------------- @@ -209,11 +166,11 @@ END FUNCTION bc_isCellEntityPresent !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_getStartIndex(obj, entityNum) RESULT(ans) + MODULE PURE FUNCTION bc_GetStartIndex(obj, entityNum) RESULT(ans) CLASS(NitscheBC_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: entityNum INTEGER(I4B) :: ans - END FUNCTION bc_getStartIndex + END FUNCTION bc_GetStartIndex END INTERFACE !---------------------------------------------------------------------------- @@ -221,11 +178,11 @@ END FUNCTION bc_getStartIndex !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_getEndIndex(obj, entityNum) RESULT(ans) + MODULE PURE FUNCTION bc_GetEndIndex(obj, entityNum) RESULT(ans) CLASS(NitscheBC_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: entityNum INTEGER(I4B) :: ans - END FUNCTION bc_getEndIndex + END FUNCTION bc_GetEndIndex END INTERFACE !---------------------------------------------------------------------------- @@ -233,11 +190,11 @@ END FUNCTION bc_getEndIndex !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_getCellElem(obj, entityNum) RESULT(ans) + MODULE PURE FUNCTION bc_GetCellElem(obj, entityNum) RESULT(ans) CLASS(NitscheBC_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: entityNum INTEGER(I4B) :: ans - END FUNCTION bc_getCellElem + END FUNCTION bc_GetCellElem END INTERFACE !---------------------------------------------------------------------------- @@ -245,11 +202,11 @@ END FUNCTION bc_getCellElem !---------------------------------------------------------------------------- INTERFACE - MODULE PURE FUNCTION bc_getLocalFacetID(obj, entityNum) RESULT(ans) + MODULE PURE FUNCTION bc_GetLocalFacetID(obj, entityNum) RESULT(ans) CLASS(NitscheBC_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: entityNum INTEGER(I4B) :: ans - END FUNCTION bc_getLocalFacetID + END FUNCTION bc_GetLocalFacetID END INTERFACE !---------------------------------------------------------------------------- @@ -293,6 +250,61 @@ MODULE FUNCTION bc_GetNitscheBCPointer(dbc, dbcNo) RESULT(ans) END FUNCTION bc_GetNitscheBCPointer END INTERFACE GetNitscheBCPointer +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-14 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) + CLASS(NitscheBC_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bc_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE NitscheBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml1(obj, table, dom, tomlName) + TYPE(NitscheBCPointer_), INTENT(INOUT) :: obj(:) + !! Should be allocated outside + TYPE(toml_table), INTENT(INOUT) :: table + !! Toml table to returned + CLASS(Domain_), TARGET, INTENT(IN) :: dom + !! domain + CHARACTER(*), INTENT(IN) :: tomlName + END SUBROUTINE bc_ImportFromToml1 +END INTERFACE NitscheBCImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE NitscheBCImportFromToml + MODULE SUBROUTINE bc_ImportFromToml2(obj, dom, tomlName, afile, & + & filename, printToml) + TYPE(NitscheBCPointer_), INTENT(INOUT) :: obj(:) + CLASS(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE bc_ImportFromToml2 +END INTERFACE NitscheBCImportFromToml + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/modules/STScalarField/src/STScalarField_Class.F90 b/src/modules/STScalarField/src/STScalarField_Class.F90 index c043d7902..761d985bb 100644 --- a/src/modules/STScalarField/src/STScalarField_Class.F90 +++ b/src/modules/STScalarField/src/STScalarField_Class.F90 @@ -20,7 +20,7 @@ MODULE STScalarField_Class USE GlobalData -USE BaseType +USE BaSetype USE String_Class USE AbstractField_Class USE AbstractNodeField_Class @@ -29,10 +29,24 @@ MODULE STScalarField_Class USE HDF5File_Class USE Domain_Class USE DirichletBC_Class +USE FiniteElement_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "STScalarField_Class" CHARACTER(*), PARAMETER :: myprefix = "STScalarField" +PUBLIC :: STScalarField_ +PUBLIC :: STScalarFieldPointer_ +PUBLIC :: SetSTScalarFieldParam +PUBLIC :: stsField_checkEssentialParam +PUBLIC :: STScalarFieldInitiate1 +PUBLIC :: STScalarFieldInitiate2 +PUBLIC :: STScalarFieldDeallocate +PUBLIC :: STScalarField +PUBLIC :: STScalarField_Pointer +PUBLIC :: STScalarFieldDisplay +PUBLIC :: STScalarFieldImport +PUBLIC :: STScalarFieldExport +PUBLIC :: STScalarFieldGetTimeCompo !---------------------------------------------------------------------------- ! STScalarField_ @@ -42,10 +56,10 @@ MODULE STScalarField_Class ! date: 25 June 2021 ! summary: STScalar field ! -!{!pages/STScalarField.md} +!{!pages/docs-api/STScalarField/STScalarField_.md} TYPE, EXTENDS(AbstractNodeField_) :: STScalarField_ - INTEGER(I4B) :: timeCompo = 0_I4B + INTEGER(I4B), PUBLIC :: timeCompo = 0_I4B CONTAINS PRIVATE PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & @@ -57,60 +71,63 @@ MODULE STScalarField_Class PROCEDURE, PUBLIC, PASS(obj) :: Export => stsField_Export PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => stsField_Deallocate FINAL :: stsField_Final - PROCEDURE, PASS(obj) :: set1 => stsField_set1 - !! set single entry - PROCEDURE, PASS(obj) :: set2 => stsField_set2 - !! set all values to a STScalar values - PROCEDURE, PASS(obj) :: set3 => stsField_set3 - !! set all values to a given STScalar - PROCEDURE, PASS(obj) :: set4 => stsField_set4 - !! set selected values to given STScalar - PROCEDURE, PASS(obj) :: set5 => stsField_set5 - !! set selected values to given STScalar - PROCEDURE, PASS(obj) :: set6 => stsField_set6 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set7 => stsField_set7 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set8 => stsField_set8 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set9 => stsField_set9 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set10 => stsField_set10 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set11 => stsField_set11 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set12 => stsField_set12 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set13 => stsField_set13 - !! set values using FEVariable - PROCEDURE, PASS(obj) :: set14 => stsField_set14 - !! set values using FEVariable - PROCEDURE, PASS(obj) :: set15 => stsField_set15 - GENERIC, PUBLIC :: set => set1, set2, set3, set4, set5, set6, & - & set7, set8, set9, set10, set11, set12, set13, set14 - PROCEDURE, PASS(obj) :: get1 => stsField_get1 - PROCEDURE, PASS(obj) :: get2 => stsField_get2 - PROCEDURE, PASS(obj) :: get3 => stsField_get3 - PROCEDURE, PASS(obj) :: get4 => stsField_get4 - PROCEDURE, PASS(obj) :: get5 => stsField_get5 - PROCEDURE, PASS(obj) :: get6 => stsField_get6 - PROCEDURE, PASS(obj) :: get7 => stsField_get7 - PROCEDURE, PASS(obj) :: get8 => stsField_get8 - PROCEDURE, PASS(obj) :: get9 => stsField_get9 - PROCEDURE, PASS(obj) :: get10 => stsField_get10 - GENERIC, PUBLIC :: get => get1, get2, get3, get4, & - & get5, get6, get7, get8, get9 + PROCEDURE, PASS(obj) :: Set1 => stsField_Set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => stsField_Set2 + !! Set all values to a STScalar values + PROCEDURE, PASS(obj) :: Set3 => stsField_Set3 + !! Set all values to a given STScalar + PROCEDURE, PASS(obj) :: Set4 => stsField_Set4 + !! Set selected values to given STScalar + PROCEDURE, PASS(obj) :: Set5 => stsField_Set5 + !! Set selected values to given STScalar + PROCEDURE, PASS(obj) :: Set6 => stsField_Set6 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set7 => stsField_Set7 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set8 => stsField_Set8 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set9 => stsField_Set9 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set10 => stsField_Set10 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set11 => stsField_Set11 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set12 => stsField_Set12 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set13 => stsField_Set13 + !! Set values using FEVariable + PROCEDURE, PASS(obj) :: Set14 => stsField_Set14 + !! Set values using FEVariable + PROCEDURE, PASS(obj) :: Set15 => stsField_Set15 + GENERIC, PUBLIC :: Set => Set1, Set2, Set3, Set4, Set5, Set6, & + & Set7, Set8, Set9, Set10, Set11, Set12, Set13, Set14 + PROCEDURE, PASS(obj) :: Get1 => stsField_Get1 + PROCEDURE, PASS(obj) :: Get2 => stsField_Get2 + PROCEDURE, PASS(obj) :: Get3 => stsField_Get3 + PROCEDURE, PASS(obj) :: Get4 => stsField_Get4 + PROCEDURE, PASS(obj) :: Get5 => stsField_Get5 + PROCEDURE, PASS(obj) :: Get6 => stsField_Get6 + PROCEDURE, PASS(obj) :: Get7 => stsField_Get7 + PROCEDURE, PASS(obj) :: Get8 => stsField_Get8 + PROCEDURE, PASS(obj) :: Get9 => stsField_Get9 + PROCEDURE, PASS(obj) :: Get10 => stsField_Get10 + GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, & + & Get5, Get6, Get7, Get8, Get9 PROCEDURE, PASS(obj) :: stsField_applyDirichletBC1 PROCEDURE, PASS(obj) :: stsField_applyDirichletBC2 GENERIC, PUBLIC :: applyDirichletBC => & & stsField_applyDirichletBC1, & & stsField_applyDirichletBC2 - !! get the entries of STScalar field - PROCEDURE, PASS(obj) :: getPointerOfComponent => & - & stsField_getPointerOfComponent + !! Get the entries of STScalar field + PROCEDURE, PASS(obj) :: GetPointerOfComponent => & + & stsField_GetPointerOfComponent END TYPE STScalarField_ -PUBLIC :: STScalarField_ +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + TYPE(STScalarField_), PARAMETER, PUBLIC :: TypeScalarField = & & STScalarField_(domains=NULL()) @@ -122,18 +139,16 @@ MODULE STScalarField_Class CLASS(STScalarField_), POINTER :: ptr => NULL() END TYPE STScalarFieldPointer_ -PUBLIC :: STScalarFieldPointer_ - !---------------------------------------------------------------------------- -! setSTScalarFieldParam@Constructor +! SetSTScalarFieldParam@Constructor !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 26 Aug 2021 -! summary: This routine is used to for setting space time scalar field +! summary: This routine is used to for Setting space time scalar field INTERFACE - MODULE SUBROUTINE setSTScalarFieldParam(param, name, timeCompo, & + MODULE SUBROUTINE SetSTScalarFieldParam(param, name, timeCompo, & & engine, fieldType, comm, global_n, local_n) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: name @@ -143,11 +158,9 @@ MODULE SUBROUTINE setSTScalarFieldParam(param, name, timeCompo, & INTEGER(I4B), OPTIONAL, INTENT(IN) :: comm INTEGER(I4B), OPTIONAL, INTENT(IN) :: global_n INTEGER(I4B), OPTIONAL, INTENT(IN) :: local_n - END SUBROUTINE setSTScalarFieldParam + END SUBROUTINE SetSTScalarFieldParam END INTERFACE -PUBLIC :: setSTScalarFieldParam - !---------------------------------------------------------------------------- ! checkEssentialParam@Constructor !---------------------------------------------------------------------------- @@ -170,8 +183,6 @@ MODULE SUBROUTINE stsField_checkEssentialParam(obj, param) END SUBROUTINE stsField_checkEssentialParam END INTERFACE -PUBLIC :: stsField_checkEssentialParam - !---------------------------------------------------------------------------- ! Initiate@Constructor !---------------------------------------------------------------------------- @@ -190,19 +201,38 @@ END SUBROUTINE stsField_checkEssentialParam ! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL INTERFACE - MODULE SUBROUTINE stsField_Initiate1(obj, param, dom) + MODULE SUBROUTINE stsField_Initiate1_old(obj, param, dom) CLASS(STScalarField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE stsField_Initiate1 + END SUBROUTINE stsField_Initiate1_old END INTERFACE +!---------------------------------------------------------------------------- +! Initiate@Constructor +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 25 June 2021 +! summary: This subroutine initiates the STScalarField_ object +! +!# Introduction +! This routine initiate the STScalar field object. +! `param` contains the information of parameters required to initiate the +! STScalar. There are essential and optional information. +! Essential information are described below. +! - `name` character defining the name of STScalar field +! - `timeCompo` is the total degree of freedom or components +! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL + INTERFACE STScalarFieldInitiate1 - MODULE PROCEDURE stsField_Initiate1 + MODULE SUBROUTINE stsField_Initiate1(obj, param, dom) + CLASS(STScalarField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE stsField_Initiate1 END INTERFACE STScalarFieldInitiate1 -PUBLIC :: STScalarFieldInitiate1 - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -227,8 +257,6 @@ END SUBROUTINE stsField_Initiate2 MODULE PROCEDURE stsField_Initiate2 END INTERFACE STScalarFieldInitiate2 -PUBLIC :: STScalarFieldInitiate2 - !---------------------------------------------------------------------------- ! Deallocate@Constructor !---------------------------------------------------------------------------- @@ -247,8 +275,6 @@ END SUBROUTINE stsField_Deallocate MODULE PROCEDURE stsField_Deallocate END INTERFACE STScalarFieldDeallocate -PUBLIC :: STScalarFieldDeallocate - !---------------------------------------------------------------------------- ! Final@Constructor !---------------------------------------------------------------------------- @@ -279,8 +305,6 @@ END FUNCTION stsField_Constructor1 MODULE PROCEDURE stsField_Constructor1 END INTERFACE STScalarField -PUBLIC :: STScalarField - !---------------------------------------------------------------------------- ! STScalarField_Pointer@Constructor !---------------------------------------------------------------------------- @@ -301,8 +325,6 @@ END FUNCTION stsField_Constructor_1 MODULE PROCEDURE stsField_Constructor_1 END INTERFACE STScalarField_Pointer -PUBLIC :: STScalarField_Pointer - !---------------------------------------------------------------------------- ! Display@IO !---------------------------------------------------------------------------- @@ -323,8 +345,6 @@ END SUBROUTINE stsField_Display MODULE PROCEDURE stsField_Display END INTERFACE STScalarFieldDisplay -PUBLIC :: STScalarFieldDisplay - !---------------------------------------------------------------------------- ! Import@IO !---------------------------------------------------------------------------- @@ -347,8 +367,6 @@ END SUBROUTINE stsField_Import MODULE PROCEDURE stsField_Import END INTERFACE STScalarFieldImport -PUBLIC :: STScalarFieldImport - !---------------------------------------------------------------------------- ! Export@IO !---------------------------------------------------------------------------- @@ -369,18 +387,16 @@ END SUBROUTINE stsField_Export MODULE PROCEDURE stsField_Export END INTERFACE STScalarFieldExport -PUBLIC :: STScalarFieldExport - !---------------------------------------------------------------------------- ! Set@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the single entry of the STScalar field +! summary: This routine Sets the single entry of the STScalar field ! !# Introduction -! This routine sets the single entry of the STScalar field. Here, val should +! This routine Sets the single entry of the STScalar field. Here, val should ! be a STScalar representing the components of a STScalar. The size of `value` ! should be same as `obj%timeCompo`. In simple words it does following. ! @@ -390,19 +406,19 @@ END SUBROUTINE stsField_Export !### Usage ! !```fortran -! call obj%set( globalNode = 10, value= 100.0_DFP*[1,1,1] ) +! call obj%Set( globalNode = 10, value= 100.0_DFP*[1,1,1] ) ! call obj%display( "test-1: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set1(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE stsField_Set1(obj, globalNode, VALUE, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set1 + END SUBROUTINE stsField_Set1 END INTERFACE !---------------------------------------------------------------------------- @@ -411,11 +427,11 @@ END SUBROUTINE stsField_set1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a STScalar field +! summary: This routine Sets all the entries of a STScalar field ! !# Introduction ! This routine work as follows. The size of value should be same as -! obj%timeCompo, then this value is set for all the nodal values +! obj%timeCompo, then this value is Set for all the nodal values ! ! STScalar( :, i ) = value( : ), for i = 1, tNodes ! @@ -423,17 +439,17 @@ END SUBROUTINE stsField_set1 !### Usage ! !```fortran -! call obj%set( value= 10.0_DFP*[1,1,1] ) +! call obj%Set( value= 10.0_DFP*[1,1,1] ) ! call obj%display( "test-2: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set2(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stsField_Set2(obj, VALUE, scale, addContribution) CLASS(STScalarField_), TARGET, INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set2 + END SUBROUTINE stsField_Set2 END INTERFACE !---------------------------------------------------------------------------- @@ -442,10 +458,10 @@ END SUBROUTINE stsField_set2 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a STScalar field +! summary: This routine Sets all the entries of a STScalar field ! !# Introduction -! This routine sets all values of `timeCompo` component of the STScalar field +! This routine Sets all values of `timeCompo` component of the STScalar field ! to given scalar value `value` ! ! STScalar( timeCompo, i ) = value, for i = 1, tNodes @@ -454,21 +470,21 @@ END SUBROUTINE stsField_set2 !### Usage ! !```fortran -! call obj%set( value= -10.0_DFP, timeCompo=1 ) -! call obj%set( value= -20.0_DFP, timeCompo=2 ) -! call obj%set( value= -30.0_DFP, timeCompo=3 ) +! call obj%Set( value= -10.0_DFP, timeCompo=1 ) +! call obj%Set( value= -20.0_DFP, timeCompo=2 ) +! call obj%Set( value= -30.0_DFP, timeCompo=3 ) ! call obj%display( "test-3: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set3(obj, VALUE, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set3(obj, VALUE, timeCompo, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set3 + END SUBROUTINE stsField_Set3 END INTERFACE !---------------------------------------------------------------------------- @@ -477,10 +493,10 @@ END SUBROUTINE stsField_set3 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STScalar field +! summary: This routine Set all the entries by using given STScalar field ! !# Introduction -! This routine set all entries of STScalar field to given STScalar +! This routine Set all entries of STScalar field to given STScalar ! Here shape of should be value(1:timeCompo, tNodes). ! ! STScalar( :, : ) = value( :, : ) @@ -489,19 +505,19 @@ END SUBROUTINE stsField_set3 !### Usage ! !```fortran -! call reallocate( real2, 3, dom%getTotalNodes() ) +! call reallocate( real2, 3, dom%GetTotalNodes() ) ! real2 = 1.0_DFP -! call obj%set( value=real2 ) +! call obj%Set( value=real2 ) ! call obj%display( "test-4: STScalar field = " ) !``` INTERFACE - MODULE SUBROUTINE stsField_set4(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stsField_Set4(obj, VALUE, scale, addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set4 + END SUBROUTINE stsField_Set4 END INTERFACE !---------------------------------------------------------------------------- @@ -510,10 +526,10 @@ END SUBROUTINE stsField_set4 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STScalar field +! summary: This routine Set all the entries by using given STScalar field ! !# Introduction -! This routine set all entries of the component `timeCompo` STScalar +! This routine Set all entries of the component `timeCompo` STScalar ! field to given fortran STScalar `value` ! ! STScalar( timeCompo, : ) = value( : ) @@ -522,21 +538,21 @@ END SUBROUTINE stsField_set4 !### Usage ! !```fortran -! call reallocate( real1, dom%getTotalNodes() ) +! call reallocate( real1, dom%GetTotalNodes() ) ! real1 = 3.0_DFP -! call obj%set( value=real1, timeCompo=3 ) +! call obj%Set( value=real1, timeCompo=3 ) ! call obj%display( "test-5: STScalar field = " ) !``` INTERFACE - MODULE SUBROUTINE stsField_set5(obj, VALUE, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set5(obj, VALUE, timeCompo, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set5 + END SUBROUTINE stsField_Set5 END INTERFACE !---------------------------------------------------------------------------- @@ -545,10 +561,10 @@ END SUBROUTINE stsField_set5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STScalar field +! summary: This routine Set all the entries by using given STScalar field ! !# Introduction -! This routine set all entries of the component `timeCompo` STScalar +! This routine Set all entries of the component `timeCompo` STScalar ! field to given scalar field `value` ! ! STScalar( timeCompo, : ) = value @@ -558,26 +574,26 @@ END SUBROUTINE stsField_set5 ! !```fortran ! call scalarObj%initiate( param, dom ) -! call scalarObj%set( value = 2.0_DFP ) -! call obj%set( value=scalarObj, timeCompo=2 ) +! call scalarObj%Set( value = 2.0_DFP ) +! call obj%Set( value=scalarObj, timeCompo=2 ) ! call obj%display( "test-6: STScalar field = ") -! ierr = param%set( key="fieldType", value=FIELD_TYPE_CONSTANT) +! ierr = param%Set( key="fieldType", value=FIELD_TYPE_CONSTANT) ! call scalarObj%Deallocate() ! call scalarObj%initiate( param, dom ) -! call scalarObj%set( value=10.0_DFP ) -! call obj%set( value=scalarObj, timeCompo=1 ) +! call scalarObj%Set( value=10.0_DFP ) +! call obj%Set( value=scalarObj, timeCompo=1 ) ! call obj%display( "test-7: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set6(obj, VALUE, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set6(obj, VALUE, timeCompo, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj CLASS(AbstractNodeField_), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set6 + END SUBROUTINE stsField_Set6 END INTERFACE !---------------------------------------------------------------------------- @@ -586,10 +602,10 @@ END SUBROUTINE stsField_set6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This soubroutine sets the selected enties to a STScalar entry value( : ) +! This soubroutine Sets the selected enties to a STScalar entry value( : ) ! Effectively it does the following: ! ! STScalar( :, globalNode ) = value( : ), for entries in global nodes @@ -601,19 +617,19 @@ END SUBROUTINE stsField_set6 ! call reallocate( real2, 3, 4) ! real2( :, 1 ) = -1.0; real2( :, 2 ) = -2.0; real2( :, 3 ) = -3.0 ! real2( :, 4 ) = -4.0 -! call obj%set( value=real2, globalNode=[1,3,5,7] ) +! call obj%Set( value=real2, globalNode=[1,3,5,7] ) ! call obj%display( "test-8: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set7(obj, VALUE, globalNode, scale, & + MODULE SUBROUTINE stsField_Set7(obj, VALUE, globalNode, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set7 + END SUBROUTINE stsField_Set7 END INTERFACE !---------------------------------------------------------------------------- @@ -622,10 +638,10 @@ END SUBROUTINE stsField_set7 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This routine sets all selected entries. +! This routine Sets all selected entries. ! STScalar( :, globalNode ) = value( :, : ) ! ! @@ -635,19 +651,19 @@ END SUBROUTINE stsField_set7 ! call reallocate( real2, 3, 4) ! real2( :, 1 ) = -1.0; real2( :, 2 ) = -2.0; real2( :, 3 ) = -3.0 ! real2( :, 4 ) = -4.0 -! call obj%set( value=real2, globalNode=[1,3,5,7] ) +! call obj%Set( value=real2, globalNode=[1,3,5,7] ) ! call obj%display( "test-8: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set8(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE stsField_Set8(obj, globalNode, VALUE, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set8 + END SUBROUTINE stsField_Set8 END INTERFACE !---------------------------------------------------------------------------- @@ -656,10 +672,10 @@ END SUBROUTINE stsField_set8 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This routine sets the selected components of selected nodes to given value +! This routine Sets the selected components of selected nodes to given value ! ! STScalar( timeCompo, globalNode ) = value( : ) ! @@ -669,12 +685,12 @@ END SUBROUTINE stsField_set8 !```fortran ! call reallocate( real1, 4) ! real1 = [1,10,100,1000] -! call obj%set( value=real1, globalNode=[1,3,5,7], timeCompo=1 ) +! call obj%Set( value=real1, globalNode=[1,3,5,7], timeCompo=1 ) ! call obj%display( "test-9: STScalar field = " ) !``` INTERFACE - MODULE SUBROUTINE stsField_set9(obj, VALUE, globalNode, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set9(obj, VALUE, globalNode, timeCompo, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) @@ -682,7 +698,7 @@ MODULE SUBROUTINE stsField_set9(obj, VALUE, globalNode, timeCompo, scale, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set9 + END SUBROUTINE stsField_Set9 END INTERFACE !---------------------------------------------------------------------------- @@ -691,7 +707,7 @@ END SUBROUTINE stsField_set9 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction ! selected components, selected nodes @@ -699,7 +715,7 @@ END SUBROUTINE stsField_set9 ! STScalar( timeCompo, globalNode ) = value INTERFACE - MODULE SUBROUTINE stsField_set10(obj, VALUE, globalNode, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set10(obj, VALUE, globalNode, timeCompo, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE @@ -707,7 +723,7 @@ MODULE SUBROUTINE stsField_set10(obj, VALUE, globalNode, timeCompo, scale, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set10 + END SUBROUTINE stsField_Set10 END INTERFACE !---------------------------------------------------------------------------- @@ -716,14 +732,14 @@ END SUBROUTINE stsField_set10 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction ! Set entries using the selected nodes using triplet. ! INTERFACE - MODULE SUBROUTINE stsField_set11(obj, VALUE, istart, iend, stride, scale, & + MODULE SUBROUTINE stsField_Set11(obj, VALUE, istart, iend, stride, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -732,7 +748,7 @@ MODULE SUBROUTINE stsField_set11(obj, VALUE, istart, iend, stride, scale, & REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set11 + END SUBROUTINE stsField_Set11 END INTERFACE !---------------------------------------------------------------------------- @@ -741,13 +757,13 @@ END SUBROUTINE stsField_set11 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the STScalar values using triplet +! summary: Set the STScalar values using triplet ! !# Introduction ! Set entries using the selected nodes using triplet. INTERFACE - MODULE SUBROUTINE stsField_set12(obj, VALUE, istart, iend, stride, scale, & + MODULE SUBROUTINE stsField_Set12(obj, VALUE, istart, iend, stride, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :) @@ -756,7 +772,7 @@ MODULE SUBROUTINE stsField_set12(obj, VALUE, istart, iend, stride, scale, & INTEGER(I4B), INTENT(IN) :: stride REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set12 + END SUBROUTINE stsField_Set12 END INTERFACE !---------------------------------------------------------------------------- @@ -771,14 +787,14 @@ END SUBROUTINE stsField_set12 ! Set entries using FEVariable INTERFACE - MODULE SUBROUTINE stsField_set13(obj, VALUE, globalNode, scale, & + MODULE SUBROUTINE stsField_Set13(obj, VALUE, globalNode, scale, & & addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj TYPE(FEVariable_), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set13 + END SUBROUTINE stsField_Set13 END INTERFACE !---------------------------------------------------------------------------- @@ -787,18 +803,18 @@ END SUBROUTINE stsField_set13 !> authors: Vikas Sharma, Ph. D. ! date: 24 Jan 2022 -! summary: set the STScalar values +! summary: Set the STScalar values ! !# Introduction ! Set entries using the selected nodes using triplet. INTERFACE - MODULE SUBROUTINE stsField_set14(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stsField_Set14(obj, VALUE, scale, addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set14 + END SUBROUTINE stsField_Set14 END INTERFACE !---------------------------------------------------------------------------- @@ -810,7 +826,7 @@ END SUBROUTINE stsField_set14 ! summary: Set the STScalarField INTERFACE - MODULE SUBROUTINE stsField_set15(obj, ivar, idof, VALUE, ivar_value, & + MODULE SUBROUTINE stsField_Set15(obj, ivar, idof, VALUE, ivar_value, & & idof_value, scale, addContribution) CLASS(STScalarField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: ivar @@ -820,7 +836,7 @@ MODULE SUBROUTINE stsField_set15(obj, ivar, idof, VALUE, ivar_value, & INTEGER(I4B), INTENT(IN) :: idof_value REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set15 + END SUBROUTINE stsField_Set15 END INTERFACE !---------------------------------------------------------------------------- @@ -844,12 +860,12 @@ END SUBROUTINE stsField_set15 !@endnote INTERFACE - MODULE SUBROUTINE stsField_get1(obj, VALUE, globalNode, timeCompo) + MODULE SUBROUTINE stsField_Get1(obj, VALUE, globalNode, timeCompo) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode INTEGER(I4B), OPTIONAL, INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get1 + END SUBROUTINE stsField_Get1 END INTERFACE !---------------------------------------------------------------------------- @@ -858,13 +874,13 @@ END SUBROUTINE stsField_get1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine get all the entries by using given STScalar field +! summary: This routine Get all the entries by using given STScalar field INTERFACE - MODULE SUBROUTINE stsField_get2(obj, VALUE) + MODULE SUBROUTINE stsField_Get2(obj, VALUE) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) - END SUBROUTINE stsField_get2 + END SUBROUTINE stsField_Get2 END INTERFACE !---------------------------------------------------------------------------- @@ -876,11 +892,11 @@ END SUBROUTINE stsField_get2 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stsField_get3(obj, VALUE, globalNode) + MODULE SUBROUTINE stsField_Get3(obj, VALUE, globalNode) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE stsField_get3 + END SUBROUTINE stsField_Get3 END INTERFACE !---------------------------------------------------------------------------- @@ -892,12 +908,12 @@ END SUBROUTINE stsField_get3 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stsField_get4(obj, VALUE, globalNode, timeCompo) + MODULE SUBROUTINE stsField_Get4(obj, VALUE, globalNode, timeCompo) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get4 + END SUBROUTINE stsField_Get4 END INTERFACE !---------------------------------------------------------------------------- @@ -909,12 +925,12 @@ END SUBROUTINE stsField_get4 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stsField_get5(obj, VALUE, globalNode, timeCompo) + MODULE SUBROUTINE stsField_Get5(obj, VALUE, globalNode, timeCompo) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get5 + END SUBROUTINE stsField_Get5 END INTERFACE !---------------------------------------------------------------------------- @@ -923,16 +939,16 @@ END SUBROUTINE stsField_get5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE stsField_get6(obj, VALUE, istart, iend, stride) + MODULE SUBROUTINE stsField_Get6(obj, VALUE, istart, iend, stride) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - END SUBROUTINE stsField_get6 + END SUBROUTINE stsField_Get6 END INTERFACE !---------------------------------------------------------------------------- @@ -941,17 +957,17 @@ END SUBROUTINE stsField_get6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE stsField_get7(obj, VALUE, istart, iend, stride, timeCompo) + MODULE SUBROUTINE stsField_Get7(obj, VALUE, istart, iend, stride, timeCompo) CLASS(STScalarField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get7 + END SUBROUTINE stsField_Get7 END INTERFACE !---------------------------------------------------------------------------- @@ -963,12 +979,12 @@ END SUBROUTINE stsField_get7 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE stsField_get8(obj, VALUE, globalNode) + MODULE SUBROUTINE stsField_Get8(obj, VALUE, globalNode) CLASS(STScalarField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE !! Nodal, Vector, SpaceTime INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE stsField_get8 + END SUBROUTINE stsField_Get8 END INTERFACE !---------------------------------------------------------------------------- @@ -980,11 +996,11 @@ END SUBROUTINE stsField_get8 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE stsField_get9(obj, VALUE, timeCompo) + MODULE SUBROUTINE stsField_Get9(obj, VALUE, timeCompo) CLASS(STScalarField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get9 + END SUBROUTINE stsField_Get9 END INTERFACE !---------------------------------------------------------------------------- @@ -996,14 +1012,14 @@ END SUBROUTINE stsField_get9 ! summary: Get values INTERFACE -MODULE SUBROUTINE stsField_get10(obj, ivar, idof, VALUE, ivar_value, idof_value) +MODULE SUBROUTINE stsField_Get10(obj, ivar, idof, VALUE, ivar_value, idof_value) CLASS(STScalarField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof INTEGER(I4B), INTENT(IN) :: ivar_value INTEGER(I4B), INTENT(IN) :: idof_value - END SUBROUTINE stsField_get10 + END SUBROUTINE stsField_Get10 END INTERFACE !---------------------------------------------------------------------------- @@ -1045,13 +1061,28 @@ END SUBROUTINE stsField_applyDirichletBC2 ! summary: This routine returns pointer to a specific component INTERFACE - MODULE FUNCTION stsField_getPointerOfComponent(obj, timeCompo) RESULT(ans) + MODULE FUNCTION stsField_GetPointerOfComponent(obj, timeCompo) RESULT(ans) CLASS(STScalarField_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), POINTER :: ans(:) - END FUNCTION stsField_getPointerOfComponent + END FUNCTION stsField_GetPointerOfComponent END INTERFACE +!---------------------------------------------------------------------------- +! GetTimeComponent@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-29 +! summary: Get time components + +INTERFACE STScalarFieldGetTimeCompo + MODULE FUNCTION stsField_GetTimeCompo(obj) RESULT(ans) + CLASS(STScalarField_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION stsField_GetTimeCompo +END INTERFACE STScalarFieldGetTimeCompo + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 b/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 index 48dd5d2b4..27660017d 100644 --- a/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 +++ b/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 @@ -20,7 +20,7 @@ MODULE STScalarFieldLis_Class USE GlobalData -USE BaseType +USE BaSetype USE String_Class USE AbstractField_Class USE AbstractNodeField_Class @@ -34,16 +34,20 @@ MODULE STScalarFieldLis_Class PRIVATE CHARACTER(*), PARAMETER :: modName = "STScalarFieldLis_Class" CHARACTER(*), PARAMETER :: myprefix = "STScalarField" +PUBLIC :: STScalarFieldLis_ +PUBLIC :: STScalarFieldLisPointer_ +PUBLIC :: STScalarFieldLis +PUBLIC :: STScalarFieldLis_Pointer !---------------------------------------------------------------------------- -! STScalarFieldLis_ +! STScalarFieldLis_ !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 2023-03-23 ! summary: STScalar field for LIS_OMP engine ! -!{!pages/STScalarFieldLis_.md} +!{!pages/docs-api/STScalarFieldLis/STScalarFieldLis_.md} TYPE, EXTENDS(STScalarField_) :: STScalarFieldLis_ #ifdef USE_LIS @@ -65,48 +69,48 @@ MODULE STScalarFieldLis_Class PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => stsField_SetSingle PROCEDURE, PASS(obj) :: SetAll => stsField_SetAll PROCEDURE, PASS(obj) :: SetMultiple => stsField_SetMultiple - PROCEDURE, PASS(obj) :: set1 => stsField_set1 - !! set single entry - PROCEDURE, PASS(obj) :: set2 => stsField_set2 - !! set all values to a STScalar values - PROCEDURE, PASS(obj) :: set3 => stsField_set3 - !! set all values to a given STScalar - PROCEDURE, PASS(obj) :: set4 => stsField_set4 - !! set selected values to given STScalar - PROCEDURE, PASS(obj) :: set5 => stsField_set5 - !! set selected values to given STScalar - PROCEDURE, PASS(obj) :: set6 => stsField_set6 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set7 => stsField_set7 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set8 => stsField_set8 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set9 => stsField_set9 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set10 => stsField_set10 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set11 => stsField_set11 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set12 => stsField_set12 - !! set values to a STScalar by using triplet - PROCEDURE, PASS(obj) :: set13 => stsField_set13 - !! set values using FEVariable - PROCEDURE, PASS(obj) :: set14 => stsField_set14 - !! set values using FEVariable + PROCEDURE, PASS(obj) :: Set1 => stsField_Set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => stsField_Set2 + !! Set all values to a STScalar values + PROCEDURE, PASS(obj) :: Set3 => stsField_Set3 + !! Set all values to a given STScalar + PROCEDURE, PASS(obj) :: Set4 => stsField_Set4 + !! Set selected values to given STScalar + PROCEDURE, PASS(obj) :: Set5 => stsField_Set5 + !! Set selected values to given STScalar + PROCEDURE, PASS(obj) :: Set6 => stsField_Set6 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set7 => stsField_Set7 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set8 => stsField_Set8 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set9 => stsField_Set9 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set10 => stsField_Set10 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set11 => stsField_Set11 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set12 => stsField_Set12 + !! Set values to a STScalar by using triplet + PROCEDURE, PASS(obj) :: Set13 => stsField_Set13 + !! Set values using FEVariable + PROCEDURE, PASS(obj) :: Set14 => stsField_Set14 + !! Set values using FEVariable ! ! @GetMethods ! PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => stsField_GetSingle - PROCEDURE, PASS(obj) :: get1 => stsField_get1 - PROCEDURE, PASS(obj) :: get2 => stsField_get2 - PROCEDURE, PASS(obj) :: get3 => stsField_get3 - PROCEDURE, PASS(obj) :: get4 => stsField_get4 - PROCEDURE, PASS(obj) :: get5 => stsField_get5 - PROCEDURE, PASS(obj) :: get6 => stsField_get6 - PROCEDURE, PASS(obj) :: get7 => stsField_get7 - PROCEDURE, PASS(obj) :: get8 => stsField_get8 - PROCEDURE, PASS(obj) :: get9 => stsField_get9 - !! get the entries of STScalar field + PROCEDURE, PASS(obj) :: Get1 => stsField_Get1 + PROCEDURE, PASS(obj) :: Get2 => stsField_Get2 + PROCEDURE, PASS(obj) :: Get3 => stsField_Get3 + PROCEDURE, PASS(obj) :: Get4 => stsField_Get4 + PROCEDURE, PASS(obj) :: Get5 => stsField_Get5 + PROCEDURE, PASS(obj) :: Get6 => stsField_Get6 + PROCEDURE, PASS(obj) :: Get7 => stsField_Get7 + PROCEDURE, PASS(obj) :: Get8 => stsField_Get8 + PROCEDURE, PASS(obj) :: Get9 => stsField_Get9 + !! Get the entries of STScalar field PROCEDURE, PUBLIC, PASS(obj) :: GetPointerOfComponent => & & stsField_GetPointerOfComponent !! Get pointer of component @@ -116,7 +120,10 @@ MODULE STScalarFieldLis_Class #endif END TYPE STScalarFieldLis_ -PUBLIC :: STScalarFieldLis_ +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + TYPE(STScalarFieldLis_), PARAMETER, PUBLIC :: TypeSTScalarField = & & STScalarFieldLis_(domains=NULL()) @@ -128,7 +135,6 @@ MODULE STScalarFieldLis_Class CLASS(STScalarFieldLis_), POINTER :: ptr => NULL() END TYPE STScalarFieldLisPointer_ -PUBLIC :: STScalarFieldLisPointer_ !---------------------------------------------------------------------------- ! STScalar@Constructor @@ -138,42 +144,30 @@ MODULE STScalarFieldLis_Class ! date: 25 June 2021 ! summary: This function returns an instance of [[STScalarFieldLis_]] -INTERFACE +INTERFACE STScalarFieldLis MODULE FUNCTION stsField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom TYPE(STScalarFieldLis_) :: ans END FUNCTION stsField_Constructor1 -END INTERFACE - -INTERFACE STScalarFieldLis - MODULE PROCEDURE stsField_Constructor1 END INTERFACE STScalarFieldLis -PUBLIC :: STScalarFieldLis - !---------------------------------------------------------------------------- -! STScalarFieldLis_Pointer@Constructor +! STScalarFieldLis_Pointer@Constructor !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 ! summary: This function returns an instance of [[STScalarFieldLis_]] -INTERFACE +INTERFACE STScalarFieldLis_Pointer MODULE FUNCTION stsField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom CLASS(STScalarFieldLis_), POINTER :: ans END FUNCTION stsField_Constructor_1 -END INTERFACE - -INTERFACE STScalarFieldLis_Pointer - MODULE PROCEDURE stsField_Constructor_1 END INTERFACE STScalarFieldLis_Pointer -PUBLIC :: STScalarFieldLis_Pointer - #ifdef USE_LIS !---------------------------------------------------------------------------- @@ -207,7 +201,7 @@ END SUBROUTINE stsField_Final MODULE SUBROUTINE stsField_Initiate1(obj, param, dom) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom END SUBROUTINE stsField_Initiate1 END INTERFACE @@ -219,14 +213,10 @@ END SUBROUTINE stsField_Initiate1 ! date: 25 June 2021 ! summary: This routine deallocates the data stored inside the STScalarFieldLis_ obj -INTERFACE +INTERFACE STScalarFieldLisDeallocate MODULE SUBROUTINE stsField_Deallocate(obj) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj END SUBROUTINE stsField_Deallocate -END INTERFACE - -INTERFACE STScalarFieldLisDeallocate - MODULE PROCEDURE stsField_Deallocate END INTERFACE STScalarFieldLisDeallocate PUBLIC :: STScalarFieldLisDeallocate @@ -260,8 +250,8 @@ MODULE SUBROUTINE stsField_Import(obj, hdf5, group, dom, domains) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE stsField_Import END INTERFACE @@ -331,14 +321,14 @@ END FUNCTION stsField_Size !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE stsField_setSingle(obj, indx, VALUE, scale, & + MODULE SUBROUTINE stsField_SetSingle(obj, indx, VALUE, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: indx REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_setSingle + END SUBROUTINE stsField_SetSingle END INTERFACE !---------------------------------------------------------------------------- @@ -346,12 +336,12 @@ END SUBROUTINE stsField_setSingle !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE stsField_setAll(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stsField_SetAll(obj, VALUE, scale, addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_setAll + END SUBROUTINE stsField_SetAll END INTERFACE !---------------------------------------------------------------------------- @@ -359,13 +349,13 @@ END SUBROUTINE stsField_setAll !---------------------------------------------------------------------------- INTERFACE -MODULE SUBROUTINE stsField_setMultiple(obj, indx, VALUE, scale, addContribution) +MODULE SUBROUTINE stsField_SetMultiple(obj, indx, VALUE, scale, addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: indx(:) REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_setMultiple + END SUBROUTINE stsField_SetMultiple END INTERFACE !---------------------------------------------------------------------------- @@ -374,10 +364,10 @@ END SUBROUTINE stsField_setMultiple !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the single entry of the STScalar field +! summary: This routine Sets the single entry of the STScalar field ! !# Introduction -! This routine sets the single entry of the STScalar field. Here, val should +! This routine Sets the single entry of the STScalar field. Here, val should ! be a STScalar representing the components of a STScalar. The size of `value` ! should be same as `obj%timeCompo`. In simple words it does following. ! @@ -387,19 +377,19 @@ END SUBROUTINE stsField_setMultiple !### Usage ! !```fortran -! call obj%set( globalNode = 10, value= 100.0_DFP*[1,1,1] ) +! call obj%Set( globalNode = 10, value= 100.0_DFP*[1,1,1] ) ! call obj%display( "test-1: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set1(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE stsField_Set1(obj, globalNode, VALUE, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set1 + END SUBROUTINE stsField_Set1 END INTERFACE !---------------------------------------------------------------------------- @@ -408,11 +398,11 @@ END SUBROUTINE stsField_set1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a STScalar field +! summary: This routine Sets all the entries of a STScalar field ! !# Introduction ! This routine work as follows. The size of value should be same as -! obj%timeCompo, then this value is set for all the nodal values +! obj%timeCompo, then this value is Set for all the nodal values ! ! STScalar( :, i ) = value( : ), for i = 1, tNodes ! @@ -420,17 +410,17 @@ END SUBROUTINE stsField_set1 !### Usage ! !```fortran -! call obj%set( value= 10.0_DFP*[1,1,1] ) +! call obj%Set( value= 10.0_DFP*[1,1,1] ) ! call obj%display( "test-2: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set2(obj, VALUE, scale, addContribution) - CLASS(STScalarFieldLis_), TARGET, INTENT(INOUT) :: obj + MODULE SUBROUTINE stsField_Set2(obj, VALUE, scale, addContribution) + CLASS(STScalarFieldLis_), TARGet, INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set2 + END SUBROUTINE stsField_Set2 END INTERFACE !---------------------------------------------------------------------------- @@ -439,10 +429,10 @@ END SUBROUTINE stsField_set2 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a STScalar field +! summary: This routine Sets all the entries of a STScalar field ! !# Introduction -! This routine sets all values of `timeCompo` component of the STScalar field +! This routine Sets all values of `timeCompo` component of the STScalar field ! to given scalar value `value` ! ! STScalar( timeCompo, i ) = value, for i = 1, tNodes @@ -451,21 +441,21 @@ END SUBROUTINE stsField_set2 !### Usage ! !```fortran -! call obj%set( value= -10.0_DFP, timeCompo=1 ) -! call obj%set( value= -20.0_DFP, timeCompo=2 ) -! call obj%set( value= -30.0_DFP, timeCompo=3 ) +! call obj%Set( value= -10.0_DFP, timeCompo=1 ) +! call obj%Set( value= -20.0_DFP, timeCompo=2 ) +! call obj%Set( value= -30.0_DFP, timeCompo=3 ) ! call obj%display( "test-3: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set3(obj, VALUE, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set3(obj, VALUE, timeCompo, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set3 + END SUBROUTINE stsField_Set3 END INTERFACE !---------------------------------------------------------------------------- @@ -474,10 +464,10 @@ END SUBROUTINE stsField_set3 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STScalar field +! summary: This routine Set all the entries by using given STScalar field ! !# Introduction -! This routine set all entries of STScalar field to given STScalar +! This routine Set all entries of STScalar field to given STScalar ! Here shape of should be value(1:timeCompo, tNodes). ! ! STScalar( :, : ) = value( :, : ) @@ -486,19 +476,19 @@ END SUBROUTINE stsField_set3 !### Usage ! !```fortran -! call reallocate( real2, 3, dom%getTotalNodes() ) +! call reallocate( real2, 3, dom%GetTotalNodes() ) ! real2 = 1.0_DFP -! call obj%set( value=real2 ) +! call obj%Set( value=real2 ) ! call obj%display( "test-4: STScalar field = " ) !``` INTERFACE - MODULE SUBROUTINE stsField_set4(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stsField_Set4(obj, VALUE, scale, addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set4 + END SUBROUTINE stsField_Set4 END INTERFACE !---------------------------------------------------------------------------- @@ -507,10 +497,10 @@ END SUBROUTINE stsField_set4 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STScalar field +! summary: This routine Set all the entries by using given STScalar field ! !# Introduction -! This routine set all entries of the component `timeCompo` STScalar +! This routine Set all entries of the component `timeCompo` STScalar ! field to given fortran STScalar `value` ! ! STScalar( timeCompo, : ) = value( : ) @@ -519,21 +509,21 @@ END SUBROUTINE stsField_set4 !### Usage ! !```fortran -! call reallocate( real1, dom%getTotalNodes() ) +! call reallocate( real1, dom%GetTotalNodes() ) ! real1 = 3.0_DFP -! call obj%set( value=real1, timeCompo=3 ) +! call obj%Set( value=real1, timeCompo=3 ) ! call obj%display( "test-5: STScalar field = " ) !``` INTERFACE - MODULE SUBROUTINE stsField_set5(obj, VALUE, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set5(obj, VALUE, timeCompo, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set5 + END SUBROUTINE stsField_Set5 END INTERFACE !---------------------------------------------------------------------------- @@ -542,10 +532,10 @@ END SUBROUTINE stsField_set5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STScalar field +! summary: This routine Set all the entries by using given STScalar field ! !# Introduction -! This routine set all entries of the component `timeCompo` STScalar +! This routine Set all entries of the component `timeCompo` STScalar ! field to given scalar field `value` ! ! STScalar( timeCompo, : ) = value @@ -555,26 +545,26 @@ END SUBROUTINE stsField_set5 ! !```fortran ! call scalarObj%initiate( param, dom ) -! call scalarObj%set( value = 2.0_DFP ) -! call obj%set( value=scalarObj, timeCompo=2 ) +! call scalarObj%Set( value = 2.0_DFP ) +! call obj%Set( value=scalarObj, timeCompo=2 ) ! call obj%display( "test-6: STScalar field = ") -! ierr = param%set( key="fieldType", value=FIELD_TYPE_CONSTANT) +! ierr = param%Set( key="fieldType", value=FIELD_TYPE_CONSTANT) ! call scalarObj%Deallocate() ! call scalarObj%initiate( param, dom ) -! call scalarObj%set( value=10.0_DFP ) -! call obj%set( value=scalarObj, timeCompo=1 ) +! call scalarObj%Set( value=10.0_DFP ) +! call obj%Set( value=scalarObj, timeCompo=1 ) ! call obj%display( "test-7: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set6(obj, VALUE, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set6(obj, VALUE, timeCompo, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj CLASS(AbstractNodeField_), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set6 + END SUBROUTINE stsField_Set6 END INTERFACE !---------------------------------------------------------------------------- @@ -583,10 +573,10 @@ END SUBROUTINE stsField_set6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This soubroutine sets the selected enties to a STScalar entry value( : ) +! This soubroutine Sets the selected enties to a STScalar entry value( : ) ! Effectively it does the following: ! ! STScalar( :, globalNode ) = value( : ), for entries in global nodes @@ -598,19 +588,19 @@ END SUBROUTINE stsField_set6 ! call reallocate( real2, 3, 4) ! real2( :, 1 ) = -1.0; real2( :, 2 ) = -2.0; real2( :, 3 ) = -3.0 ! real2( :, 4 ) = -4.0 -! call obj%set( value=real2, globalNode=[1,3,5,7] ) +! call obj%Set( value=real2, globalNode=[1,3,5,7] ) ! call obj%display( "test-8: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set7(obj, VALUE, globalNode, scale, & + MODULE SUBROUTINE stsField_Set7(obj, VALUE, globalNode, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set7 + END SUBROUTINE stsField_Set7 END INTERFACE !---------------------------------------------------------------------------- @@ -619,10 +609,10 @@ END SUBROUTINE stsField_set7 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This routine sets all selected entries. +! This routine Sets all selected entries. ! STScalar( :, globalNode ) = value( :, : ) ! ! @@ -632,19 +622,19 @@ END SUBROUTINE stsField_set7 ! call reallocate( real2, 3, 4) ! real2( :, 1 ) = -1.0; real2( :, 2 ) = -2.0; real2( :, 3 ) = -3.0 ! real2( :, 4 ) = -4.0 -! call obj%set( value=real2, globalNode=[1,3,5,7] ) +! call obj%Set( value=real2, globalNode=[1,3,5,7] ) ! call obj%display( "test-8: STScalar field = ") !``` INTERFACE - MODULE SUBROUTINE stsField_set8(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE stsField_Set8(obj, globalNode, VALUE, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set8 + END SUBROUTINE stsField_Set8 END INTERFACE !---------------------------------------------------------------------------- @@ -653,10 +643,10 @@ END SUBROUTINE stsField_set8 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This routine sets the selected components of selected nodes to given value +! This routine Sets the selected components of selected nodes to given value ! ! STScalar( timeCompo, globalNode ) = value( : ) ! @@ -666,12 +656,12 @@ END SUBROUTINE stsField_set8 !```fortran ! call reallocate( real1, 4) ! real1 = [1,10,100,1000] -! call obj%set( value=real1, globalNode=[1,3,5,7], timeCompo=1 ) +! call obj%Set( value=real1, globalNode=[1,3,5,7], timeCompo=1 ) ! call obj%display( "test-9: STScalar field = " ) !``` INTERFACE - MODULE SUBROUTINE stsField_set9(obj, VALUE, globalNode, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set9(obj, VALUE, globalNode, timeCompo, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) @@ -679,7 +669,7 @@ MODULE SUBROUTINE stsField_set9(obj, VALUE, globalNode, timeCompo, scale, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set9 + END SUBROUTINE stsField_Set9 END INTERFACE !---------------------------------------------------------------------------- @@ -688,7 +678,7 @@ END SUBROUTINE stsField_set9 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction ! selected components, selected nodes @@ -696,7 +686,7 @@ END SUBROUTINE stsField_set9 ! STScalar( timeCompo, globalNode ) = value INTERFACE - MODULE SUBROUTINE stsField_set10(obj, VALUE, globalNode, timeCompo, scale, & + MODULE SUBROUTINE stsField_Set10(obj, VALUE, globalNode, timeCompo, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE @@ -704,7 +694,7 @@ MODULE SUBROUTINE stsField_set10(obj, VALUE, globalNode, timeCompo, scale, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set10 + END SUBROUTINE stsField_Set10 END INTERFACE !---------------------------------------------------------------------------- @@ -713,14 +703,14 @@ END SUBROUTINE stsField_set10 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction ! Set entries using the selected nodes using triplet. ! INTERFACE - MODULE SUBROUTINE stsField_set11(obj, VALUE, istart, iend, stride, scale, & + MODULE SUBROUTINE stsField_Set11(obj, VALUE, istart, iend, stride, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -729,7 +719,7 @@ MODULE SUBROUTINE stsField_set11(obj, VALUE, istart, iend, stride, scale, & REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set11 + END SUBROUTINE stsField_Set11 END INTERFACE !---------------------------------------------------------------------------- @@ -738,13 +728,13 @@ END SUBROUTINE stsField_set11 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the STScalar values using triplet +! summary: Set the STScalar values using triplet ! !# Introduction ! Set entries using the selected nodes using triplet. INTERFACE - MODULE SUBROUTINE stsField_set12(obj, VALUE, istart, iend, stride, scale, & + MODULE SUBROUTINE stsField_Set12(obj, VALUE, istart, iend, stride, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :) @@ -753,7 +743,7 @@ MODULE SUBROUTINE stsField_set12(obj, VALUE, istart, iend, stride, scale, & INTEGER(I4B), INTENT(IN) :: stride REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set12 + END SUBROUTINE stsField_Set12 END INTERFACE !---------------------------------------------------------------------------- @@ -768,14 +758,14 @@ END SUBROUTINE stsField_set12 ! Set entries using FEVariable INTERFACE - MODULE SUBROUTINE stsField_set13(obj, VALUE, globalNode, scale, & + MODULE SUBROUTINE stsField_Set13(obj, VALUE, globalNode, scale, & & addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj TYPE(FEVariable_), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set13 + END SUBROUTINE stsField_Set13 END INTERFACE !---------------------------------------------------------------------------- @@ -784,18 +774,18 @@ END SUBROUTINE stsField_set13 !> authors: Vikas Sharma, Ph. D. ! date: 24 Jan 2022 -! summary: set the STScalar values +! summary: Set the STScalar values ! !# Introduction ! Set entries using the selected nodes using triplet. INTERFACE - MODULE SUBROUTINE stsField_set14(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stsField_Set14(obj, VALUE, scale, addContribution) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stsField_set14 + END SUBROUTINE stsField_Set14 END INTERFACE !---------------------------------------------------------------------------- @@ -819,12 +809,12 @@ END SUBROUTINE stsField_set14 !@endnote INTERFACE - MODULE SUBROUTINE stsField_get1(obj, VALUE, globalNode, timeCompo) + MODULE SUBROUTINE stsField_Get1(obj, VALUE, globalNode, timeCompo) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode INTEGER(I4B), OPTIONAL, INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get1 + END SUBROUTINE stsField_Get1 END INTERFACE !---------------------------------------------------------------------------- @@ -833,13 +823,13 @@ END SUBROUTINE stsField_get1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine get all the entries by using given STScalar field +! summary: This routine Get all the entries by using given STScalar field INTERFACE - MODULE SUBROUTINE stsField_get2(obj, VALUE) + MODULE SUBROUTINE stsField_Get2(obj, VALUE) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) - END SUBROUTINE stsField_get2 + END SUBROUTINE stsField_Get2 END INTERFACE !---------------------------------------------------------------------------- @@ -851,11 +841,11 @@ END SUBROUTINE stsField_get2 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stsField_get3(obj, VALUE, globalNode) + MODULE SUBROUTINE stsField_Get3(obj, VALUE, globalNode) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE stsField_get3 + END SUBROUTINE stsField_Get3 END INTERFACE !---------------------------------------------------------------------------- @@ -867,12 +857,12 @@ END SUBROUTINE stsField_get3 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stsField_get4(obj, VALUE, globalNode, timeCompo) + MODULE SUBROUTINE stsField_Get4(obj, VALUE, globalNode, timeCompo) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get4 + END SUBROUTINE stsField_Get4 END INTERFACE !---------------------------------------------------------------------------- @@ -884,12 +874,12 @@ END SUBROUTINE stsField_get4 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stsField_get5(obj, VALUE, globalNode, timeCompo) + MODULE SUBROUTINE stsField_Get5(obj, VALUE, globalNode, timeCompo) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get5 + END SUBROUTINE stsField_Get5 END INTERFACE !---------------------------------------------------------------------------- @@ -898,16 +888,16 @@ END SUBROUTINE stsField_get5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE stsField_get6(obj, VALUE, istart, iend, stride) + MODULE SUBROUTINE stsField_Get6(obj, VALUE, istart, iend, stride) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - END SUBROUTINE stsField_get6 + END SUBROUTINE stsField_Get6 END INTERFACE !---------------------------------------------------------------------------- @@ -916,17 +906,17 @@ END SUBROUTINE stsField_get6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE stsField_get7(obj, VALUE, istart, iend, stride, timeCompo) + MODULE SUBROUTINE stsField_Get7(obj, VALUE, istart, iend, stride, timeCompo) CLASS(STScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get7 + END SUBROUTINE stsField_Get7 END INTERFACE !---------------------------------------------------------------------------- @@ -938,12 +928,12 @@ END SUBROUTINE stsField_get7 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE stsField_get8(obj, VALUE, globalNode) + MODULE SUBROUTINE stsField_Get8(obj, VALUE, globalNode) CLASS(STScalarFieldLis_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE !! Nodal, Vector, SpaceTime INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE stsField_get8 + END SUBROUTINE stsField_Get8 END INTERFACE !---------------------------------------------------------------------------- @@ -955,11 +945,11 @@ END SUBROUTINE stsField_get8 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE stsField_get9(obj, VALUE, timeCompo) + MODULE SUBROUTINE stsField_Get9(obj, VALUE, timeCompo) CLASS(STScalarFieldLis_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stsField_get9 + END SUBROUTINE stsField_Get9 END INTERFACE !---------------------------------------------------------------------------- @@ -971,11 +961,11 @@ END SUBROUTINE stsField_get9 ! summary: This routine returns pointer to a specific component INTERFACE - MODULE FUNCTION stsField_getPointerOfComponent(obj, timeCompo) RESULT(ans) + MODULE FUNCTION stsField_GetPointerOfComponent(obj, timeCompo) RESULT(ans) CLASS(STScalarFieldLis_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), POINTER :: ans(:) - END FUNCTION stsField_getPointerOfComponent + END FUNCTION stsField_GetPointerOfComponent END INTERFACE !---------------------------------------------------------------------------- @@ -983,10 +973,10 @@ END FUNCTION stsField_getPointerOfComponent !---------------------------------------------------------------------------- INTERFACE - MODULE FUNCTION stsField_getPointer(obj) RESULT(ans) - CLASS(STScalarFieldLis_), TARGET, INTENT(IN) :: obj + MODULE FUNCTION stsField_GetPointer(obj) RESULT(ans) + CLASS(STScalarFieldLis_), TARGet, INTENT(IN) :: obj REAL(DFP), POINTER :: ans(:) - END FUNCTION stsField_getPointer + END FUNCTION stsField_GetPointer END INTERFACE !---------------------------------------------------------------------------- @@ -998,11 +988,11 @@ END FUNCTION stsField_getPointer ! summary: Get single entry INTERFACE - MODULE SUBROUTINE stsField_getSingle(obj, indx, VALUE) + MODULE SUBROUTINE stsField_GetSingle(obj, indx, VALUE) CLASS(STScalarFieldLis_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: indx REAL(DFP), INTENT(OUT) :: VALUE - END SUBROUTINE stsField_getSingle + END SUBROUTINE stsField_GetSingle END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/modules/STVectorField/src/STVectorField_Class.F90 b/src/modules/STVectorField/src/STVectorField_Class.F90 index 497711477..a2969fff2 100644 --- a/src/modules/STVectorField/src/STVectorField_Class.F90 +++ b/src/modules/STVectorField/src/STVectorField_Class.F90 @@ -20,7 +20,7 @@ MODULE STVectorField_Class USE GlobalData -USE BaseType +USE BaSetype USE AbstractField_Class USE AbstractNodeField_Class USE ExceptionHandler_Class, ONLY: e @@ -28,10 +28,21 @@ MODULE STVectorField_Class USE HDF5File_Class USE Domain_Class USE DirichletBC_Class +USE FiniteElement_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "STVectorField_Class" CHARACTER(*), PARAMETER :: myprefix = "STVectorField" +PUBLIC :: STVectorFieldPointer_ +PUBLIC :: SetSTVectorFieldParam +PUBLIC :: STVectorFieldInitiate1 +PUBLIC :: STVectorFieldInitiate2 +PUBLIC :: STVectorFieldDeallocate +PUBLIC :: STVectorField +PUBLIC :: STVectorField_Pointer +PUBLIC :: STVectorFieldDisplay +PUBLIC :: STVectorFieldImport +PUBLIC :: STVectorFieldExport !---------------------------------------------------------------------------- ! STVectorField_ @@ -41,9 +52,10 @@ MODULE STVectorField_Class ! date: 25 June 2021 ! summary: STVector field ! -!{!pages/STVectorField_.md} +!{!pages/docs-api/STVectorField/STVectorField_.md} TYPE, EXTENDS(AbstractNodeField_) :: STVectorField_ + ! private INTEGER(I4B) :: spaceCompo = 0_I4B INTEGER(I4B) :: timeCompo = 0_I4B CONTAINS @@ -57,59 +69,59 @@ MODULE STVectorField_Class PROCEDURE, PUBLIC, PASS(obj) :: Display => stvField_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => stvField_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => stvField_Export - PROCEDURE, PASS(obj) :: set1 => stvField_set1 - !! set single entry - PROCEDURE, PASS(obj) :: set2 => stvField_set2 - !! set all values to a STVector values - PROCEDURE, PASS(obj) :: set3 => stvField_set3 - !! set all values to a given STvector - PROCEDURE, PASS(obj) :: set4 => stvField_set4 - !! set selected values to given STVector - PROCEDURE, PASS(obj) :: set5 => stvField_set5 - !! set selected values to given STvector - PROCEDURE, PASS(obj) :: set6 => stvField_set6 - !! set values to a STVector by using triplet - PROCEDURE, PASS(obj) :: set7 => stvField_set7 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set8 => stvField_set8 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set9 => stvField_set9 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set10 => stvField_set10 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set11 => stvField_set11 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set12 => stvField_set12 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set13 => stvField_set13 - PROCEDURE, PASS(obj) :: set14 => stvField_set14 - !! set values to a STvector by using triplet - PROCEDURE, PASS(obj) :: set15 => stvField_set15 - GENERIC, PUBLIC :: set => & - & set1, set2, set3, set4, set5, set6, & - & set7, set8, set9, set10, set11, & - & set12, set13, set14, set15 - PROCEDURE, PASS(obj) :: get1 => stvField_get1 - PROCEDURE, PASS(obj) :: get2 => stvField_get2 - PROCEDURE, PASS(obj) :: get3 => stvField_get3 - PROCEDURE, PASS(obj) :: get4 => stvField_get4 - PROCEDURE, PASS(obj) :: get5 => stvField_get5 - PROCEDURE, PASS(obj) :: get6 => stvField_get6 - PROCEDURE, PASS(obj) :: get7 => stvField_get7 - PROCEDURE, PASS(obj) :: get8 => stvField_get8 - PROCEDURE, PASS(obj) :: get9 => stvField_get9 - PROCEDURE, PASS(obj) :: get10 => stvField_get10 - PROCEDURE, PASS(obj) :: get11 => stvField_get11 - GENERIC, PUBLIC :: get => get1, get2, get3, get4, get5, & - & get6, get7, get8, get9, get10, get11 - PROCEDURE, PUBLIC, PASS(obj) :: getPointerOfComponent => & - & stvField_getPointerOfComponent - !! get the entries of STVector field - PROCEDURE, PASS(obj) :: stvField_applyDirichletBC1 - PROCEDURE, PASS(obj) :: stvField_applyDirichletBC2 - GENERIC, PUBLIC :: applyDirichletBC => & - & stvField_applyDirichletBC1, & - & stvField_applyDirichletBC2 + PROCEDURE, PASS(obj) :: Set1 => stvField_Set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => stvField_Set2 + !! Set all values to a STVector values + PROCEDURE, PASS(obj) :: Set3 => stvField_Set3 + !! Set all values to a given STvector + PROCEDURE, PASS(obj) :: Set4 => stvField_Set4 + !! Set selected values to given STVector + PROCEDURE, PASS(obj) :: Set5 => stvField_Set5 + !! Set selected values to given STvector + PROCEDURE, PASS(obj) :: Set6 => stvField_Set6 + !! Set values to a STVector by using triplet + PROCEDURE, PASS(obj) :: Set7 => stvField_Set7 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set8 => stvField_Set8 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set9 => stvField_Set9 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set10 => stvField_Set10 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set11 => stvField_Set11 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set12 => stvField_Set12 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set13 => stvField_Set13 + PROCEDURE, PASS(obj) :: Set14 => stvField_Set14 + !! Set values to a STvector by using triplet + PROCEDURE, PASS(obj) :: Set15 => stvField_Set15 + GENERIC, PUBLIC :: Set => & + & Set1, Set2, Set3, Set4, Set5, Set6, & + & Set7, Set8, Set9, Set10, Set11, & + & Set12, Set13, Set14, Set15 + PROCEDURE, PASS(obj) :: Get1 => stvField_Get1 + PROCEDURE, PASS(obj) :: Get2 => stvField_Get2 + PROCEDURE, PASS(obj) :: Get3 => stvField_Get3 + PROCEDURE, PASS(obj) :: Get4 => stvField_Get4 + PROCEDURE, PASS(obj) :: Get5 => stvField_Get5 + PROCEDURE, PASS(obj) :: Get6 => stvField_Get6 + PROCEDURE, PASS(obj) :: Get7 => stvField_Get7 + PROCEDURE, PASS(obj) :: Get8 => stvField_Get8 + PROCEDURE, PASS(obj) :: Get9 => stvField_Get9 + PROCEDURE, PASS(obj) :: Get10 => stvField_Get10 + PROCEDURE, PASS(obj) :: Get11 => stvField_Get11 + GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, Get5, & + & Get6, Get7, Get8, Get9, Get10, Get11 + PROCEDURE, PUBLIC, PASS(obj) :: GetPointerOfComponent => & + & stvField_GetPointerOfComponent + !! Get the entries of STVector field + PROCEDURE, PASS(obj) :: stvField_ApplyDirichletBC1 + PROCEDURE, PASS(obj) :: stvField_ApplyDirichletBC2 + GENERIC, PUBLIC :: ApplyDirichletBC => & + & stvField_ApplyDirichletBC1, & + & stvField_ApplyDirichletBC2 END TYPE STVectorField_ PUBLIC :: STVectorField_ @@ -124,18 +136,16 @@ MODULE STVectorField_Class CLASS(STVectorField_), POINTER :: ptr => NULL() END TYPE STVectorFieldPointer_ -PUBLIC :: STVectorFieldPointer_ - !---------------------------------------------------------------------------- -! setSTVectorFieldParam@ConstructorMethods +! SetSTVectorFieldParam@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 26 Aug 2021 -! summary: set essential parameter +! summary: Set essential parameter INTERFACE - MODULE SUBROUTINE setSTVectorFieldParam(param, name, engine, & + MODULE SUBROUTINE SetSTVectorFieldParam(param, name, engine, & & spaceCompo, timeCompo, fieldType, comm, local_n, global_n) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: name @@ -146,11 +156,9 @@ MODULE SUBROUTINE setSTVectorFieldParam(param, name, engine, & INTEGER(I4B), OPTIONAL, INTENT(IN) :: comm INTEGER(I4B), OPTIONAL, INTENT(IN) :: global_n INTEGER(I4B), OPTIONAL, INTENT(IN) :: local_n - END SUBROUTINE setSTVectorFieldParam + END SUBROUTINE SetSTVectorFieldParam END INTERFACE -PUBLIC :: setSTVectorFieldParam - !---------------------------------------------------------------------------- ! checkEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -186,19 +194,41 @@ END SUBROUTINE stvField_checkEssentialParam ! - `timeCompo` is the total degree of freedom or components ! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL -INTERFACE +INTERFACE STVectorFieldInitiate1 MODULE SUBROUTINE stvField_Initiate1(obj, param, dom) CLASS(STVectorField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom END SUBROUTINE stvField_Initiate1 -END INTERFACE - -INTERFACE STVectorFieldInitiate1 - MODULE PROCEDURE stvField_Initiate1 END INTERFACE STVectorFieldInitiate1 -PUBLIC :: STVectorFieldInitiate1 +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 25 June 2021 +! summary: This subroutine initiates the space-time vector field +! +!# Introduction +! +! This routine initiate the space-time vector field object. +! `param` contains the information of parameters required to initiate the +! this field. +! There are essential and optional information. +! Essential information are described below. +! - `name` character defining the name of STvector field +! - `spaceCompo` is the total degree of freedom or components +! - `timeCompo` is the total degree of freedom or components +! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL + +INTERFACE + MODULE SUBROUTINE stvField_Initiate1_old(obj, param, dom) + CLASS(STVectorField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(Domain_), TARGet, INTENT(IN) :: dom + END SUBROUTINE stvField_Initiate1_old +END INTERFACE !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods @@ -208,7 +238,7 @@ END SUBROUTINE stvField_Initiate1 ! date: 2023-03-29 ! summary: Initiate2 -INTERFACE +INTERFACE STVectorFieldInitiate2 MODULE SUBROUTINE stvField_Initiate2(obj, obj2, copyFull, copyStructure, & & usePointer) CLASS(STVectorField_), INTENT(INOUT) :: obj @@ -218,14 +248,8 @@ MODULE SUBROUTINE stvField_Initiate2(obj, obj2, copyFull, copyStructure, & LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer END SUBROUTINE stvField_Initiate2 -END INTERFACE - -INTERFACE STVectorFieldInitiate2 - MODULE PROCEDURE stvField_Initiate2 END INTERFACE STVectorFieldInitiate2 -PUBLIC :: STVectorFieldInitiate2 - !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -234,18 +258,12 @@ END SUBROUTINE stvField_Initiate2 ! date: 25 June 2021 ! summary: This routine deallocates the data stored inside the STVectorField_ obj -INTERFACE +INTERFACE STVectorFieldDeallocate MODULE SUBROUTINE stvField_Deallocate(obj) CLASS(STVectorField_), INTENT(INOUT) :: obj END SUBROUTINE stvField_Deallocate -END INTERFACE - -INTERFACE STVectorFieldDeallocate - MODULE PROCEDURE stvField_Deallocate END INTERFACE STVectorFieldDeallocate -PUBLIC :: STVectorFieldDeallocate - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -264,20 +282,14 @@ END SUBROUTINE stvField_Final ! date: 25 June 2021 ! summary: This function returns an instance of [[STVectorField_]] -INTERFACE +INTERFACE STVectorField MODULE FUNCTION stvField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom TYPE(STVectorField_) :: ans END FUNCTION stvField_Constructor1 -END INTERFACE - -INTERFACE STVectorField - MODULE PROCEDURE stvField_Constructor1 END INTERFACE STVectorField -PUBLIC :: STVectorField - !---------------------------------------------------------------------------- ! STVectorField_Pointer@ConstructorMethods !---------------------------------------------------------------------------- @@ -286,20 +298,14 @@ END FUNCTION stvField_Constructor1 ! date: 25 June 2021 ! summary: This function returns an instance of [[STVectorField_]] -INTERFACE +INTERFACE STVectorField_Pointer MODULE FUNCTION stvField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom CLASS(STVectorField_), POINTER :: ans END FUNCTION stvField_Constructor_1 -END INTERFACE - -INTERFACE STVectorField_Pointer - MODULE PROCEDURE stvField_Constructor_1 END INTERFACE STVectorField_Pointer -PUBLIC :: STVectorField_Pointer - !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- @@ -308,20 +314,14 @@ END FUNCTION stvField_Constructor_1 ! date: 26 June 2021 ! summary: Display the content of [[STVectorField_]] -INTERFACE +INTERFACE STVectorFieldDisplay MODULE SUBROUTINE stvField_Display(obj, msg, unitNo) CLASS(STVectorField_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo END SUBROUTINE stvField_Display -END INTERFACE - -INTERFACE STVectorFieldDisplay - MODULE PROCEDURE stvField_Display END INTERFACE STVectorFieldDisplay -PUBLIC :: STVectorFieldDisplay - !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- @@ -330,22 +330,16 @@ END SUBROUTINE stvField_Display ! date: 16 July 2021 ! summary: This routine Imports the content -INTERFACE +INTERFACE STVectorFieldImport MODULE SUBROUTINE stvField_Import(obj, hdf5, group, dom, domains) CLASS(STVectorField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE stvField_Import -END INTERFACE - -INTERFACE STVectorFieldImport - MODULE PROCEDURE stvField_Import END INTERFACE STVectorFieldImport -PUBLIC :: STVectorFieldImport - !---------------------------------------------------------------------------- ! Export@IOMethods !---------------------------------------------------------------------------- @@ -354,30 +348,24 @@ END SUBROUTINE stvField_Import ! date: 16 July 2021 ! summary: This routine Exports the content -INTERFACE +INTERFACE STVectorFieldExport MODULE SUBROUTINE stvField_Export(obj, hdf5, group) CLASS(STVectorField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE stvField_Export -END INTERFACE - -INTERFACE STVectorFieldExport - MODULE PROCEDURE stvField_Export END INTERFACE STVectorFieldExport -PUBLIC :: STVectorFieldExport - !---------------------------------------------------------------------------- ! Set@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the single entry of the STVector field +! summary: This routine Sets the single entry of the STVector field ! !# Introduction -! This routine sets the single entry of the STvector field. Here, +! This routine Sets the single entry of the STvector field. Here, ! `value` is a two dimensional array of real numbers, denoting the space-time ! components of the vector. The first index denotes the space components, ! second index denotes the time-components. As a result, total number of rows @@ -387,14 +375,14 @@ END SUBROUTINE stvField_Export ! STvector( :, :, globalNode ) = value( :, : ) INTERFACE - MODULE SUBROUTINE stvField_set1(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE stvField_Set1(obj, globalNode, VALUE, scale, & & addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set1 + END SUBROUTINE stvField_Set1 END INTERFACE !---------------------------------------------------------------------------- @@ -403,10 +391,10 @@ END SUBROUTINE stvField_set1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a STVector field +! summary: This routine Sets all the entries of a STVector field ! !# Introduction -! This routine sets all entries of the STvector field. Here, +! This routine Sets all entries of the STvector field. Here, ! `value` is a two dimensional array of real numbers, denoting the space-time ! components of the vector. The first index denotes the space components, ! second index denotes the time-components. As a result, total number of rows @@ -416,12 +404,12 @@ END SUBROUTINE stvField_set1 ! STvector( :, :, i ) = value( :, : ), for i = 1, tNodes INTERFACE - MODULE SUBROUTINE stvField_set2(obj, VALUE, scale, addContribution) - CLASS(STVectorField_), TARGET, INTENT(INOUT) :: obj + MODULE SUBROUTINE stvField_Set2(obj, VALUE, scale, addContribution) + CLASS(STVectorField_), TARGet, INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set2 + END SUBROUTINE stvField_Set2 END INTERFACE !---------------------------------------------------------------------------- @@ -430,17 +418,17 @@ END SUBROUTINE stvField_set2 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a STVector field +! summary: This routine Sets all the entries of a STVector field ! !# Introduction -! This routine sets all entries of the space-time vector field. Here +! This routine Sets all entries of the space-time vector field. Here ! `spaceCompo` and `timeCompo` are the spatial temporal components, which we ! want to replace by a scalar value `value`. ! ! STvector( spaceCompo, timeCompo, i ) = value, for i = 1, tNodes INTERFACE - MODULE SUBROUTINE stvField_set3(obj, VALUE, spaceCompo, timeCompo, & + MODULE SUBROUTINE stvField_Set3(obj, VALUE, spaceCompo, timeCompo, & & scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE @@ -448,7 +436,7 @@ MODULE SUBROUTINE stvField_set3(obj, VALUE, spaceCompo, timeCompo, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set3 + END SUBROUTINE stvField_Set3 END INTERFACE !---------------------------------------------------------------------------- @@ -457,10 +445,10 @@ END SUBROUTINE stvField_set3 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using given STVector field +! summary: This routine Set all the entries by using given STVector field ! !# Introduction -! This routine set all entries of the space-time vector. +! This routine Set all entries of the space-time vector. ! The first index of `value` denotes the spatial components ! The second index of `value` denotes the temporal components ! The thrid index of `value` denotes the node number @@ -468,12 +456,12 @@ END SUBROUTINE stvField_set3 ! STvector( :, :, : ) = value( :, :, : ) INTERFACE - MODULE SUBROUTINE stvField_set4(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stvField_Set4(obj, VALUE, scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set4 + END SUBROUTINE stvField_Set4 END INTERFACE !---------------------------------------------------------------------------- @@ -482,11 +470,11 @@ END SUBROUTINE stvField_set4 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all nodal values of a given space-time component +! summary: This routine Set all nodal values of a given space-time component ! !# Introduction ! -! This routine sets all entries of the space-time vector field. Here +! This routine Sets all entries of the space-time vector field. Here ! `spaceCompo` and `timeCompo` are the spatial temporal components, which we ! want to replace by a vector `value`. Note that the size of `value` should ! be equal to the total number of nodes in the mesh. @@ -494,7 +482,7 @@ END SUBROUTINE stvField_set4 ! STvector( spaceCompo, timeCompo, : ) = value( : ) INTERFACE - MODULE SUBROUTINE stvField_set5(obj, VALUE, spaceCompo, timeCompo, & + MODULE SUBROUTINE stvField_Set5(obj, VALUE, spaceCompo, timeCompo, & & scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) @@ -502,7 +490,7 @@ MODULE SUBROUTINE stvField_set5(obj, VALUE, spaceCompo, timeCompo, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set5 + END SUBROUTINE stvField_Set5 END INTERFACE !---------------------------------------------------------------------------- @@ -511,11 +499,11 @@ END SUBROUTINE stvField_set5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all nodal values of a given space-time component +! summary: This routine Set all nodal values of a given space-time component ! !# Introduction ! -! This routine sets all entries of the space-time vector field. Here +! This routine Sets all entries of the space-time vector field. Here ! `spaceCompo` and `timeCompo` are the spatial temporal components, which we ! want to replace by a vector of scalars. These vectors of scalar are stored ! inside a scalar field called `value`. Note that the size of `value` should @@ -524,7 +512,7 @@ END SUBROUTINE stvField_set5 ! STvector( spaceCompo, : ) = value INTERFACE - MODULE SUBROUTINE stvField_set6(obj, VALUE, spaceCompo, timeCompo, & + MODULE SUBROUTINE stvField_Set6(obj, VALUE, spaceCompo, timeCompo, & & scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj CLASS(AbstractNodeField_), INTENT(IN) :: VALUE @@ -532,7 +520,7 @@ MODULE SUBROUTINE stvField_set6(obj, VALUE, spaceCompo, timeCompo, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set6 + END SUBROUTINE stvField_Set6 END INTERFACE !---------------------------------------------------------------------------- @@ -541,10 +529,10 @@ END SUBROUTINE stvField_set6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This soubroutine sets the selected enties in space-time vector to a +! This soubroutine Sets the selected enties in space-time vector to a ! constant space-time nodal values. Here globalNode is the list of global ! node number. `value` is a rank2 array of real numbers. Its first index ! denotes the space component and second component denotes the time component. @@ -554,14 +542,14 @@ END SUBROUTINE stvField_set6 ! STvector( :, :, globalNode ) = value( :, : ), for entries in global nodes INTERFACE - MODULE SUBROUTINE stvField_set7(obj, VALUE, globalNode, scale, & + MODULE SUBROUTINE stvField_Set7(obj, VALUE, globalNode, scale, & & addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set7 + END SUBROUTINE stvField_Set7 END INTERFACE !---------------------------------------------------------------------------- @@ -570,10 +558,10 @@ END SUBROUTINE stvField_set7 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This routine sets selected entries of space-time vector field. Here +! This routine Sets selected entries of space-time vector field. Here ! globalNode contains the list of global nodes where values will be changed. ! ! - `value` is a rank-3 array. @@ -588,14 +576,14 @@ END SUBROUTINE stvField_set7 ! STvector( :, :, globalNode ) = value( :, :, : ) INTERFACE - MODULE SUBROUTINE stvField_set8(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE stvField_Set8(obj, globalNode, VALUE, scale, & & addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:, :, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set8 + END SUBROUTINE stvField_Set8 END INTERFACE !---------------------------------------------------------------------------- @@ -604,15 +592,15 @@ END SUBROUTINE stvField_set8 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction -! This routine sets the selected components of selected nodes to a given value +! This routine Sets the selected components of selected nodes to a given value ! ! STvector( spaceCompo, globalNode ) = value( : ) INTERFACE - MODULE SUBROUTINE stvField_set9(obj, VALUE, globalNode, spaceCompo, & + MODULE SUBROUTINE stvField_Set9(obj, VALUE, globalNode, spaceCompo, & & timeCompo, scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) @@ -621,7 +609,7 @@ MODULE SUBROUTINE stvField_set9(obj, VALUE, globalNode, spaceCompo, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set9 + END SUBROUTINE stvField_Set9 END INTERFACE !---------------------------------------------------------------------------- @@ -630,7 +618,7 @@ END SUBROUTINE stvField_set9 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries ! !# Introduction ! selected components, selected nodes @@ -638,7 +626,7 @@ END SUBROUTINE stvField_set9 ! STvector( spaceCompo, globalNode ) = value INTERFACE - MODULE SUBROUTINE stvField_set10(obj, VALUE, globalNode, spaceCompo, & + MODULE SUBROUTINE stvField_Set10(obj, VALUE, globalNode, spaceCompo, & & timeCompo, scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE @@ -647,7 +635,7 @@ MODULE SUBROUTINE stvField_set10(obj, VALUE, globalNode, spaceCompo, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set10 + END SUBROUTINE stvField_Set10 END INTERFACE !---------------------------------------------------------------------------- @@ -656,10 +644,10 @@ END SUBROUTINE stvField_set10 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE stvField_set11(obj, VALUE, istart, iend, stride, & + MODULE SUBROUTINE stvField_Set11(obj, VALUE, istart, iend, stride, & & scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -668,7 +656,7 @@ MODULE SUBROUTINE stvField_set11(obj, VALUE, istart, iend, stride, & REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set11 + END SUBROUTINE stvField_Set11 END INTERFACE !---------------------------------------------------------------------------- @@ -677,10 +665,10 @@ END SUBROUTINE stvField_set11 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the STvector values using triplet +! summary: Set the STvector values using triplet INTERFACE - MODULE SUBROUTINE stvField_set12(obj, VALUE, istart, iend, stride, & + MODULE SUBROUTINE stvField_Set12(obj, VALUE, istart, iend, stride, & & scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :, :) @@ -689,7 +677,7 @@ MODULE SUBROUTINE stvField_set12(obj, VALUE, istart, iend, stride, & INTEGER(I4B), INTENT(IN) :: stride REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set12 + END SUBROUTINE stvField_Set12 END INTERFACE !---------------------------------------------------------------------------- @@ -698,17 +686,17 @@ END SUBROUTINE stvField_set12 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the STvector values using triplet +! summary: Set the STvector values using triplet INTERFACE - MODULE SUBROUTINE stvField_set13(obj, VALUE, globalNode, scale, & + MODULE SUBROUTINE stvField_Set13(obj, VALUE, globalNode, scale, & & addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj TYPE(FEVariable_), INTENT(IN) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set13 + END SUBROUTINE stvField_Set13 END INTERFACE !---------------------------------------------------------------------------- @@ -717,15 +705,15 @@ END SUBROUTINE stvField_set13 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the STvector values using triplet +! summary: Set the STvector values using triplet INTERFACE - MODULE SUBROUTINE stvField_set14(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE stvField_Set14(obj, VALUE, scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set14 + END SUBROUTINE stvField_Set14 END INTERFACE !---------------------------------------------------------------------------- @@ -737,7 +725,7 @@ END SUBROUTINE stvField_set14 ! summary: Setvalues INTERFACE - MODULE SUBROUTINE stvField_set15(obj, ivar, idof, VALUE, ivar_value, & + MODULE SUBROUTINE stvField_Set15(obj, ivar, idof, VALUE, ivar_value, & & idof_value, scale, addContribution) CLASS(STVectorField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: ivar @@ -747,7 +735,7 @@ MODULE SUBROUTINE stvField_set15(obj, ivar, idof, VALUE, ivar_value, & INTEGER(I4B), INTENT(IN) :: idof_value REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE stvField_set15 + END SUBROUTINE stvField_Set15 END INTERFACE !---------------------------------------------------------------------------- @@ -768,14 +756,14 @@ END SUBROUTINE stvField_set15 ! - Either globalNode should be present or INTERFACE - MODULE SUBROUTINE stvField_get1(obj, VALUE, globalNode, spaceCompo, & + MODULE SUBROUTINE stvField_Get1(obj, VALUE, globalNode, spaceCompo, & & timeCompo) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode INTEGER(I4B), OPTIONAL, INTENT(IN) :: spaceCompo INTEGER(I4B), OPTIONAL, INTENT(IN) :: timeCompo - END SUBROUTINE stvField_get1 + END SUBROUTINE stvField_Get1 END INTERFACE !---------------------------------------------------------------------------- @@ -784,7 +772,7 @@ END SUBROUTINE stvField_get1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine get all the entries of the space-time vector field +! summary: This routine Get all the entries of the space-time vector field ! !# Introduction ! This routine returns all the nodal values of a space-time nodal vector field. @@ -795,10 +783,10 @@ END SUBROUTINE stvField_get1 ! - the third index denotes the node number. INTERFACE - MODULE SUBROUTINE stvField_get2(obj, VALUE) + MODULE SUBROUTINE stvField_Get2(obj, VALUE) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :, :) - END SUBROUTINE stvField_get2 + END SUBROUTINE stvField_Get2 END INTERFACE !---------------------------------------------------------------------------- @@ -821,11 +809,11 @@ END SUBROUTINE stvField_get2 !@endnote INTERFACE - MODULE SUBROUTINE stvField_get3(obj, VALUE, globalNode) + MODULE SUBROUTINE stvField_Get3(obj, VALUE, globalNode) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :, :) INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE stvField_get3 + END SUBROUTINE stvField_Get3 END INTERFACE !---------------------------------------------------------------------------- @@ -844,14 +832,14 @@ END SUBROUTINE stvField_get3 ! that the length of value should be equal to the size of globalNode vector. INTERFACE - MODULE SUBROUTINE stvField_get4(obj, VALUE, globalNode, spaceCompo, & + MODULE SUBROUTINE stvField_Get4(obj, VALUE, globalNode, spaceCompo, & & timeCompo) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stvField_get4 + END SUBROUTINE stvField_Get4 END INTERFACE !---------------------------------------------------------------------------- @@ -863,14 +851,14 @@ END SUBROUTINE stvField_get4 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stvField_get5(obj, VALUE, globalNode, spaceCompo, & + MODULE SUBROUTINE stvField_Get5(obj, VALUE, globalNode, spaceCompo, & & timeCompo) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stvField_get5 + END SUBROUTINE stvField_Get5 END INTERFACE !---------------------------------------------------------------------------- @@ -882,13 +870,13 @@ END SUBROUTINE stvField_get5 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stvField_get6(obj, VALUE, istart, iend, stride) + MODULE SUBROUTINE stvField_Get6(obj, VALUE, istart, iend, stride) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :, :) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - END SUBROUTINE stvField_get6 + END SUBROUTINE stvField_Get6 END INTERFACE !---------------------------------------------------------------------------- @@ -900,7 +888,7 @@ END SUBROUTINE stvField_get6 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE stvField_get7(obj, VALUE, istart, iend, stride, & + MODULE SUBROUTINE stvField_Get7(obj, VALUE, istart, iend, stride, & & spaceCompo, timeCompo) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) @@ -909,7 +897,7 @@ MODULE SUBROUTINE stvField_get7(obj, VALUE, istart, iend, stride, & INTEGER(I4B), INTENT(IN) :: stride INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE stvField_get7 + END SUBROUTINE stvField_Get7 END INTERFACE !---------------------------------------------------------------------------- @@ -921,11 +909,11 @@ END SUBROUTINE stvField_get7 ! summary: This routine returns the space-time value at given node number INTERFACE - MODULE SUBROUTINE stvField_get8(obj, VALUE, globalNode) + MODULE SUBROUTINE stvField_Get8(obj, VALUE, globalNode) CLASS(STVectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: globalNode - END SUBROUTINE stvField_get8 + END SUBROUTINE stvField_Get8 END INTERFACE !---------------------------------------------------------------------------- @@ -937,11 +925,11 @@ END SUBROUTINE stvField_get8 ! summary: This routine returns the space-time value at given node number INTERFACE - MODULE SUBROUTINE stvField_get9(obj, VALUE, globalNode) + MODULE SUBROUTINE stvField_Get9(obj, VALUE, globalNode) CLASS(STVectorField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE stvField_get9 + END SUBROUTINE stvField_Get9 END INTERFACE !---------------------------------------------------------------------------- @@ -953,16 +941,16 @@ END SUBROUTINE stvField_get9 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE stvField_get10(obj, VALUE, spaceCompo, timeCompo) + MODULE SUBROUTINE stvField_Get10(obj, VALUE, spaceCompo, timeCompo) CLASS(STVectorField_), INTENT(IN) :: obj CLASS(AbstractField_), INTENT(INOUT) :: VALUE INTEGER(I4B), OPTIONAL, INTENT(IN) :: spaceCompo INTEGER(I4B), OPTIONAL, INTENT(IN) :: timeCompo - END SUBROUTINE stvField_get10 + END SUBROUTINE stvField_Get10 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -970,18 +958,18 @@ END SUBROUTINE stvField_get10 ! summary: REturns the value INTERFACE -MODULE SUBROUTINE stvField_get11(obj, ivar, idof, VALUE, ivar_value, idof_value) +MODULE SUBROUTINE stvField_Get11(obj, ivar, idof, VALUE, ivar_value, idof_value) CLASS(STVectorField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof INTEGER(I4B), INTENT(IN) :: ivar_value INTEGER(I4B), INTENT(IN) :: idof_value - END SUBROUTINE stvField_get11 + END SUBROUTINE stvField_Get11 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -989,14 +977,14 @@ END SUBROUTINE stvField_get11 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE stvField_applyDirichletBC1(obj, dbc) + MODULE SUBROUTINE stvField_ApplyDirichletBC1(obj, dbc) CLASS(STVectorField_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc - END SUBROUTINE stvField_applyDirichletBC1 + END SUBROUTINE stvField_ApplyDirichletBC1 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -1004,14 +992,14 @@ END SUBROUTINE stvField_applyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE stvField_applyDirichletBC2(obj, dbc) + MODULE SUBROUTINE stvField_ApplyDirichletBC2(obj, dbc) CLASS(STVectorField_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) - END SUBROUTINE stvField_applyDirichletBC2 + END SUBROUTINE stvField_ApplyDirichletBC2 END INTERFACE !---------------------------------------------------------------------------- -! getPointerOfComponent@GetMethods +! GetPointerOfComponent@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -1019,13 +1007,13 @@ END SUBROUTINE stvField_applyDirichletBC2 ! summary: This routine returns pointer to a specific component INTERFACE - MODULE FUNCTION stvField_getPointerOfComponent(obj, spaceCompo, timeCompo) & + MODULE FUNCTION stvField_GetPointerOfComponent(obj, spaceCompo, timeCompo) & & RESULT(ans) CLASS(STVectorField_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), POINTER :: ans(:) - END FUNCTION stvField_getPointerOfComponent + END FUNCTION stvField_GetPointerOfComponent END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index 935b55726..044f8a0d6 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -21,7 +21,7 @@ MODULE ScalarField_Class USE GlobalData USE String_Class -USE BaseType +USE BaSetype USE AbstractField_Class USE AbstractNodeField_Class USE ExceptionHandler_Class, ONLY: e @@ -29,6 +29,7 @@ MODULE ScalarField_Class USE HDF5File_Class USE Domain_Class USE DirichletBC_Class +USE FiniteElement_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "ScalarField_Class" @@ -41,6 +42,7 @@ MODULE ScalarField_Class PUBLIC :: ScalarField PUBLIC :: ScalarField_Pointer PUBLIC :: ScalarFieldImport +PUBLIC :: ScalarFieldDeallocate !---------------------------------------------------------------------------- ! ScalarField_ @@ -59,27 +61,27 @@ MODULE ScalarField_Class & sField_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => sField_Initiate1 FINAL :: sField_Final - PROCEDURE, PASS(obj) :: Set1 => sField_set1 + PROCEDURE, PASS(obj) :: Set1 => sField_Set1 !! Set single entry - PROCEDURE, PASS(obj) :: Set2 => sField_set2 + PROCEDURE, PASS(obj) :: Set2 => sField_Set2 !! Set all values to a scalar values - PROCEDURE, PASS(obj) :: Set3 => sField_set3 + PROCEDURE, PASS(obj) :: Set3 => sField_Set3 !! Set all values to a given vector - PROCEDURE, PASS(obj) :: Set4 => sField_set4 + PROCEDURE, PASS(obj) :: Set4 => sField_Set4 !! Set selected values to given scalar - PROCEDURE, PASS(obj) :: Set5 => sField_set5 + PROCEDURE, PASS(obj) :: Set5 => sField_Set5 !! Set selected values to given vector - PROCEDURE, PASS(obj) :: Set6 => sField_set6 + PROCEDURE, PASS(obj) :: Set6 => sField_Set6 !! Set values to a scalar by using triplet - PROCEDURE, PASS(obj) :: Set7 => sField_set7 + PROCEDURE, PASS(obj) :: Set7 => sField_Set7 !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set8 => sField_set8 + PROCEDURE, PASS(obj) :: Set8 => sField_Set8 !! This method is used for assignment operator - PROCEDURE, PASS(obj) :: Set9 => sField_set9 + PROCEDURE, PASS(obj) :: Set9 => sField_Set9 !! Set selected values using FEVariable - PROCEDURE, PASS(obj) :: Set10 => sField_set10 + PROCEDURE, PASS(obj) :: Set10 => sField_Set10 !! Set selected values using FEVariable - PROCEDURE, PASS(obj) :: Set11 => sField_set11 + PROCEDURE, PASS(obj) :: Set11 => sField_Set11 !! Set selected values using FEVariable GENERIC, PUBLIC :: Set => Set1, Set2, Set3, Set4, & & Set5, Set6, Set7, Set8, Set9, Set10, Set11 @@ -104,12 +106,12 @@ MODULE ScalarField_Class GENERIC, PUBLIC :: ApplyDirichletBC => & & sField_ApplyDirichletBC1, & & sField_ApplyDirichletBC2 - !! + !! Apply Dirichlet Boundary Condition PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => sField_Import END TYPE ScalarField_ !---------------------------------------------------------------------------- -! +! !---------------------------------------------------------------------------- TYPE(ScalarField_), PARAMETER, PUBLIC :: & @@ -184,15 +186,34 @@ END SUBROUTINE sField_CheckEssentialParam ! Essential information are described below. INTERFACE - MODULE SUBROUTINE sField_Initiate1(obj, param, dom) + MODULE SUBROUTINE sField_Initiate_old(obj, param, dom) CLASS(ScalarField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom - END SUBROUTINE sField_Initiate1 + TYPE(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE sField_Initiate_old END INTERFACE +!---------------------------------------------------------------------------- +! Initiate@Constructor +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 25 June 2021 +! summary: This subroutine initiates the ScalarField_ object +! +!# Introduction +! +! This routine initiate the [[ScalarField_]] object. +! `param` contains the information of parameters required to initiate the +! scalar field. There are essential and optional information. +! Essential information are described below. + INTERFACE ScalarFieldInitiate1 - MODULE PROCEDURE sField_Initiate1 + MODULE SUBROUTINE sField_Initiate1(obj, param, dom) + CLASS(ScalarField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE sField_Initiate1 END INTERFACE ScalarFieldInitiate1 !---------------------------------------------------------------------------- @@ -205,6 +226,16 @@ MODULE SUBROUTINE sField_Final(obj) END SUBROUTINE sField_Final END INTERFACE +!---------------------------------------------------------------------------- +! Final@Constructor +!---------------------------------------------------------------------------- + +INTERFACE ScalarFieldDeallocate + MODULE SUBROUTINE sField_Deallocate(obj) + TYPE(ScalarField_), INTENT(INOUT) :: obj + END SUBROUTINE sField_Deallocate +END INTERFACE ScalarFieldDeallocate + !---------------------------------------------------------------------------- ! Vector@Constructor !---------------------------------------------------------------------------- @@ -216,7 +247,7 @@ END SUBROUTINE sField_Final INTERFACE MODULE FUNCTION sField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom TYPE(ScalarField_) :: ans END FUNCTION sField_Constructor1 END INTERFACE @@ -236,7 +267,7 @@ END FUNCTION sField_Constructor1 INTERFACE MODULE FUNCTION sField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom CLASS(ScalarField_), POINTER :: ans END FUNCTION sField_Constructor_1 END INTERFACE @@ -258,8 +289,8 @@ MODULE SUBROUTINE sField_Import(obj, hdf5, group, dom, domains) CLASS(ScalarField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE sField_Import END INTERFACE diff --git a/src/modules/ScalarFieldLis/src/ScalarFieldLis_Class.F90 b/src/modules/ScalarFieldLis/src/ScalarFieldLis_Class.F90 index c58325e50..0c6e49543 100644 --- a/src/modules/ScalarFieldLis/src/ScalarFieldLis_Class.F90 +++ b/src/modules/ScalarFieldLis/src/ScalarFieldLis_Class.F90 @@ -21,7 +21,7 @@ MODULE ScalarFieldLis_Class USE GlobalData USE String_Class -USE BaseType +USE BaSetype USE AbstractField_Class USE AbstractNodeField_Class USE ScalarField_Class @@ -34,6 +34,10 @@ MODULE ScalarFieldLis_Class PRIVATE CHARACTER(*), PARAMETER :: modName = "ScalarFieldLis_Class" CHARACTER(*), PARAMETER :: myPrefix = "ScalarField" +PUBLIC :: ScalarFieldLis_ +PUBLIC :: ScalarFieldLisPointer_ +PUBLIC :: ScalarFieldLis +PUBLIC :: ScalarFieldLis_Pointer !---------------------------------------------------------------------------- ! ScalarField_ @@ -66,50 +70,53 @@ MODULE ScalarFieldLis_Class PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => sField_SetSingle PROCEDURE, PASS(obj) :: SetAll => sField_SetAll PROCEDURE, PASS(obj) :: SetMultiple => sField_SetMultiple - PROCEDURE, PASS(obj) :: set1 => sField_set1 - !! set single entry - PROCEDURE, PASS(obj) :: set2 => sField_set2 - !! set all values to a scalar values - PROCEDURE, PASS(obj) :: set3 => sField_set3 - !! set all values to a given vector - PROCEDURE, PASS(obj) :: set4 => sField_set4 - !! set selected values to given scalar - PROCEDURE, PASS(obj) :: set5 => sField_set5 - !! set selected values to given vector - PROCEDURE, PASS(obj) :: set6 => sField_set6 - !! set values to a scalar by using triplet - PROCEDURE, PASS(obj) :: set7 => sField_set7 - !! set values to a vector by using triplet - PROCEDURE, PASS(obj) :: set8 => sField_set8 + PROCEDURE, PASS(obj) :: Set1 => sField_Set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => sField_Set2 + !! Set all values to a scalar values + PROCEDURE, PASS(obj) :: Set3 => sField_Set3 + !! Set all values to a given vector + PROCEDURE, PASS(obj) :: Set4 => sField_Set4 + !! Set selected values to given scalar + PROCEDURE, PASS(obj) :: Set5 => sField_Set5 + !! Set selected values to given vector + PROCEDURE, PASS(obj) :: Set6 => sField_Set6 + !! Set values to a scalar by using triplet + PROCEDURE, PASS(obj) :: Set7 => sField_Set7 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set8 => sField_Set8 !! This method is used for assignment operator - PROCEDURE, PASS(obj) :: set9 => sField_set9 + PROCEDURE, PASS(obj) :: Set9 => sField_Set9 !! Set selected values using FEVariable - PROCEDURE, PASS(obj) :: set10 => sField_set10 + PROCEDURE, PASS(obj) :: Set10 => sField_Set10 !! Set selected values using FEVariable ! ! @GetMethods ! - PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => sField_getSingle - PROCEDURE, PASS(obj) :: get1 => sField_get1 - !! get single entry - PROCEDURE, PASS(obj) :: get2 => sField_get2 - !! get all values in Real vector - PROCEDURE, PASS(obj) :: get3 => sField_get3 - !! get selected values - PROCEDURE, PASS(obj) :: get4 => sField_get4 - !! get values from triplet - PROCEDURE, PASS(obj) :: get5 => sField_get5 - PROCEDURE, PASS(obj) :: get6 => sField_get6 - !! get selected values in FEVariable - PROCEDURE, PASS(obj) :: sField_applyDirichletBC1 - PROCEDURE, PASS(obj) :: sField_applyDirichletBC2 + PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => sField_GetSingle + PROCEDURE, PASS(obj) :: Get1 => sField_Get1 + !! Get single entry + PROCEDURE, PASS(obj) :: Get2 => sField_Get2 + !! Get all values in Real vector + PROCEDURE, PASS(obj) :: Get3 => sField_Get3 + !! Get selected values + PROCEDURE, PASS(obj) :: Get4 => sField_Get4 + !! Get values from triplet + PROCEDURE, PASS(obj) :: Get5 => sField_Get5 + PROCEDURE, PASS(obj) :: Get6 => sField_Get6 + !! Get selected values in FEVariable + PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC1 + PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC2 !! #endif END TYPE ScalarFieldLis_ -PUBLIC :: ScalarFieldLis_ -TYPE(ScalarFieldLis_), PARAMETER, PUBLIC :: TypeScalarFieldLis =& -& ScalarFieldLis_(domains=NULL()) +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE(ScalarFieldLis_), PARAMETER, PUBLIC :: TypeScalarFieldLis = & + & ScalarFieldLis_(domains=NULL()) !---------------------------------------------------------------------------- ! ScalarFieldPointer_ @@ -119,8 +126,6 @@ MODULE ScalarFieldLis_Class CLASS(ScalarFieldLis_), POINTER :: ptr => NULL() END TYPE ScalarFieldLisPointer_ -PUBLIC :: ScalarFieldLisPointer_ - !---------------------------------------------------------------------------- ! Final@Constructor !---------------------------------------------------------------------------- @@ -139,20 +144,14 @@ END SUBROUTINE sField_Final ! date: 25 June 2021 ! summary: This function returns an instance of [[ScalarFieldLis_]] -INTERFACE +INTERFACE ScalarFieldLis MODULE FUNCTION sField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom TYPE(ScalarFieldLis_) :: ans END FUNCTION sField_Constructor1 -END INTERFACE - -INTERFACE ScalarFieldLis - MODULE PROCEDURE sField_Constructor1 END INTERFACE ScalarFieldLis -PUBLIC :: ScalarFieldLis - !---------------------------------------------------------------------------- ! ScalarFieldLis_Pointer@Constructor !---------------------------------------------------------------------------- @@ -161,20 +160,14 @@ END FUNCTION sField_Constructor1 ! date: 25 June 2021 ! summary: This function returns an instance of [[ScalarFieldLis_]] -INTERFACE +INTERFACE ScalarFieldLis_Pointer MODULE FUNCTION sField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom CLASS(ScalarFieldLis_), POINTER :: ans END FUNCTION sField_Constructor_1 -END INTERFACE - -INTERFACE ScalarFieldLis_Pointer - MODULE PROCEDURE sField_Constructor_1 END INTERFACE ScalarFieldLis_Pointer -PUBLIC :: ScalarFieldLis_Pointer - #ifdef USE_LIS !---------------------------------------------------------------------------- @@ -261,10 +254,10 @@ END FUNCTION sField_Size !---------------------------------------------------------------------------- INTERFACE - MODULE FUNCTION sField_getPointer(obj) RESULT(ans) - CLASS(ScalarFieldLis_), TARGET, INTENT(IN) :: obj + MODULE FUNCTION sField_GetPointer(obj) RESULT(ans) + CLASS(ScalarFieldLis_), TARGet, INTENT(IN) :: obj REAL(DFP), POINTER :: ans(:) - END FUNCTION sField_getPointer + END FUNCTION sField_GetPointer END INTERFACE !---------------------------------------------------------------------------- @@ -279,7 +272,7 @@ END FUNCTION sField_getPointer MODULE SUBROUTINE sField_Initiate1(obj, param, dom) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom + TYPE(Domain_), TARGet, INTENT(IN) :: dom END SUBROUTINE sField_Initiate1 END INTERFACE @@ -292,8 +285,8 @@ MODULE SUBROUTINE sField_Import(obj, hdf5, group, dom, domains) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE sField_Import END INTERFACE @@ -302,14 +295,14 @@ END SUBROUTINE sField_Import !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE sField_setSingle(obj, indx, VALUE, scale, & + MODULE SUBROUTINE sField_SetSingle(obj, indx, VALUE, scale, & & addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: indx REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_setSingle + END SUBROUTINE sField_SetSingle END INTERFACE !---------------------------------------------------------------------------- @@ -317,12 +310,12 @@ END SUBROUTINE sField_setSingle !---------------------------------------------------------------------------- INTERFACE - MODULE SUBROUTINE sField_setAll(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_SetAll(obj, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_setAll + END SUBROUTINE sField_SetAll END INTERFACE !---------------------------------------------------------------------------- @@ -330,13 +323,13 @@ END SUBROUTINE sField_setAll !---------------------------------------------------------------------------- INTERFACE -MODULE SUBROUTINE sField_setMultiple(obj, indx, VALUE, scale, addContribution) +MODULE SUBROUTINE sField_SetMultiple(obj, indx, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: indx(:) REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_setMultiple + END SUBROUTINE sField_SetMultiple END INTERFACE !---------------------------------------------------------------------------- @@ -345,17 +338,17 @@ END SUBROUTINE sField_setMultiple !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the single entry of the scalar field +! summary: This routine Sets the single entry of the scalar field INTERFACE - MODULE SUBROUTINE sField_set1(obj, globalNode, VALUE, scale, & + MODULE SUBROUTINE sField_Set1(obj, globalNode, VALUE, scale, & & addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set1 + END SUBROUTINE sField_Set1 END INTERFACE !---------------------------------------------------------------------------- @@ -364,15 +357,15 @@ END SUBROUTINE sField_set1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets all the entries of a scalar field +! summary: This routine Sets all the entries of a scalar field INTERFACE - MODULE SUBROUTINE sField_set2(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set2(obj, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set2 + END SUBROUTINE sField_Set2 END INTERFACE !---------------------------------------------------------------------------- @@ -381,15 +374,15 @@ END SUBROUTINE sField_set2 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine set all the entries by using a fortran vector +! summary: This routine Set all the entries by using a fortran vector INTERFACE - MODULE SUBROUTINE sField_set3(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set3(obj, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set3 + END SUBROUTINE sField_Set3 END INTERFACE !---------------------------------------------------------------------------- @@ -398,16 +391,16 @@ END SUBROUTINE sField_set3 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the multiple entries +! summary: This routine Sets the multiple entries INTERFACE - MODULE SUBROUTINE sField_set4(obj, globalNode, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set4(obj, globalNode, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set4 + END SUBROUTINE sField_Set4 END INTERFACE !---------------------------------------------------------------------------- @@ -416,16 +409,16 @@ END SUBROUTINE sField_set4 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the multiple entries +! summary: This routine Sets the multiple entries INTERFACE - MODULE SUBROUTINE sField_set5(obj, globalNode, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set5(obj, globalNode, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set5 + END SUBROUTINE sField_Set5 END INTERFACE !---------------------------------------------------------------------------- @@ -434,10 +427,10 @@ END SUBROUTINE sField_set5 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries using triplet +! summary: This routine Sets the selected entries using triplet INTERFACE - MODULE SUBROUTINE sField_set6(obj, istart, iend, stride, VALUE, & + MODULE SUBROUTINE sField_Set6(obj, istart, iend, stride, VALUE, & & scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -446,7 +439,7 @@ MODULE SUBROUTINE sField_set6(obj, istart, iend, stride, VALUE, & REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set6 + END SUBROUTINE sField_Set6 END INTERFACE !---------------------------------------------------------------------------- @@ -455,10 +448,10 @@ END SUBROUTINE sField_set6 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: set the vector vals using triplet +! summary: Set the vector vals using triplet INTERFACE - MODULE SUBROUTINE sField_set7(obj, istart, iend, stride, VALUE, & + MODULE SUBROUTINE sField_Set7(obj, istart, iend, stride, VALUE, & & scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart @@ -467,7 +460,7 @@ MODULE SUBROUTINE sField_set7(obj, istart, iend, stride, VALUE, & REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set7 + END SUBROUTINE sField_Set7 END INTERFACE !---------------------------------------------------------------------------- @@ -479,10 +472,10 @@ END SUBROUTINE sField_set7 ! summary: used for assignment operator INTERFACE - MODULE SUBROUTINE sField_set8(obj, obj2) + MODULE SUBROUTINE sField_Set8(obj, obj2) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj CLASS(ScalarField_), INTENT(IN) :: obj2 - END SUBROUTINE sField_set8 + END SUBROUTINE sField_Set8 END INTERFACE !---------------------------------------------------------------------------- @@ -491,17 +484,17 @@ END SUBROUTINE sField_set8 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine sets the selected entries using [[FEVariable_]] +! summary: This routine Sets the selected entries using [[FEVariable_]] INTERFACE - MODULE SUBROUTINE sField_set9(obj, globalNode, VALUE, scale, addContribution) + MODULE SUBROUTINE sField_Set9(obj, globalNode, VALUE, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) TYPE(FEVariable_), INTENT(IN) :: VALUE !! Scalar, Nodal, FEVariable (Space or Constant) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE sField_set9 + END SUBROUTINE sField_Set9 END INTERFACE !---------------------------------------------------------------------------- @@ -513,12 +506,12 @@ END SUBROUTINE sField_set9 ! summary: obj=obj+scalar*obj2 INTERFACE - MODULE SUBROUTINE sField_set10(obj, obj2, scale, addContribution) + MODULE SUBROUTINE sField_Set10(obj, obj2, scale, addContribution) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj CLASS(ScalarField_), INTENT(IN) :: obj2 REAL(DFP), INTENT(IN) :: scale LOGICAL(LGT), INTENT(IN) :: addContribution - END SUBROUTINE sField_set10 + END SUBROUTINE sField_Set10 END INTERFACE !---------------------------------------------------------------------------- @@ -530,15 +523,15 @@ END SUBROUTINE sField_set10 ! summary: Get single entry INTERFACE - MODULE SUBROUTINE sField_getSingle(obj, indx, VALUE) + MODULE SUBROUTINE sField_GetSingle(obj, indx, VALUE) CLASS(ScalarFieldLis_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: indx REAL(DFP), INTENT(OUT) :: VALUE - END SUBROUTINE sField_getSingle + END SUBROUTINE sField_GetSingle END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -546,15 +539,15 @@ END SUBROUTINE sField_getSingle ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE sField_get1(obj, VALUE, globalNode) + MODULE SUBROUTINE sField_Get1(obj, VALUE, globalNode) CLASS(ScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode - END SUBROUTINE sField_get1 + END SUBROUTINE sField_Get1 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -562,14 +555,14 @@ END SUBROUTINE sField_get1 ! summary: This routine returns all the entries by using given scalar field INTERFACE - MODULE SUBROUTINE sField_get2(obj, VALUE) + MODULE SUBROUTINE sField_Get2(obj, VALUE) CLASS(ScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - END SUBROUTINE sField_get2 + END SUBROUTINE sField_Get2 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -577,15 +570,15 @@ END SUBROUTINE sField_get2 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE sField_get3(obj, VALUE, globalNode) + MODULE SUBROUTINE sField_Get3(obj, VALUE, globalNode) CLASS(ScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE sField_get3 + END SUBROUTINE sField_Get3 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -593,17 +586,17 @@ END SUBROUTINE sField_get3 ! summary: returns the value using triplet INTERFACE - MODULE SUBROUTINE sField_get4(obj, VALUE, istart, iend, stride) + MODULE SUBROUTINE sField_Get4(obj, VALUE, istart, iend, stride) CLASS(ScalarFieldLis_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - END SUBROUTINE sField_get4 + END SUBROUTINE sField_Get4 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -611,16 +604,16 @@ END SUBROUTINE sField_get4 ! summary: returns the selected values in FEVariable INTERFACE - MODULE SUBROUTINE sField_get5(obj, VALUE, globalNode) + MODULE SUBROUTINE sField_Get5(obj, VALUE, globalNode) CLASS(ScalarFieldLis_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE !! Scalar Nodal FEVariable INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE sField_get5 + END SUBROUTINE sField_Get5 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -628,14 +621,14 @@ END SUBROUTINE sField_get5 ! summary: returns the selected values in FEVariable INTERFACE - MODULE SUBROUTINE sField_get6(obj, VALUE) + MODULE SUBROUTINE sField_Get6(obj, VALUE) CLASS(ScalarFieldLis_), INTENT(IN) :: obj CLASS(ScalarField_), INTENT(INOUT) :: VALUE - END SUBROUTINE sField_get6 + END SUBROUTINE sField_Get6 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -643,14 +636,14 @@ END SUBROUTINE sField_get6 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE sField_applyDirichletBC1(obj, dbc) + MODULE SUBROUTINE sField_ApplyDirichletBC1(obj, dbc) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc - END SUBROUTINE sField_applyDirichletBC1 + END SUBROUTINE sField_ApplyDirichletBC1 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -658,15 +651,16 @@ END SUBROUTINE sField_applyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE sField_applyDirichletBC2(obj, dbc) + MODULE SUBROUTINE sField_ApplyDirichletBC2(obj, dbc) CLASS(ScalarFieldLis_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) - END SUBROUTINE sField_applyDirichletBC2 + END SUBROUTINE sField_ApplyDirichletBC2 END INTERFACE !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- + #endif END MODULE ScalarFieldLis_Class diff --git a/src/modules/TxtFile/src/ConstructorMethods.inc b/src/modules/TxtFile/src/ConstructorMethods.inc deleted file mode 100644 index a69f2dfd6..000000000 --- a/src/modules/TxtFile/src/ConstructorMethods.inc +++ /dev/null @@ -1,93 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Initiate the txt file - -INTERFACE - MODULE SUBROUTINE txt_initiate(obj, filename, unit, status, access, form, & - & position, action, pad, recl, comment, separator, delimiter) - CLASS(TxtFile_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: filename - INTEGER(I4B), OPTIONAL, INTENT(IN) :: unit - !! User specified unit number, it should not be `stdout, stdin, stderr` - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: status - !! OLD, NEW, SCRATCH, REPLACE, UNKNOWN - !! If UNKNOWN then we use REPLACE - !! Default is REPLACE - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: access - !! DIRECT, SEQUENTIAL, STREAM - !! Default is SEQUENTIAL - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: form - !! FORMATTED, UNFORMATTED - !! Default is FORMATTED - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: position - !! REWIND, APPEND, ASIS - !! Default is ASIS - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: action - !! READ, WRITE, READWRITE - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: pad - !! YES, NO - !! Default is YES - INTEGER(I4B), OPTIONAL, INTENT(IN) :: recl - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: comment - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: separator - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: delimiter - END SUBROUTINE txt_initiate -END INTERFACE - -INTERFACE TxtFileInitiate - MODULE PROCEDURE txt_initiate -END INTERFACE TxtFileInitiate - -PUBLIC :: TxtFileInitiate - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Deallocate the data - -INTERFACE - MODULE SUBROUTINE txt_Deallocate(obj, Delete) - CLASS(TxtFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete - END SUBROUTINE txt_Deallocate -END INTERFACE - -INTERFACE TxtFileDeallocate - MODULE PROCEDURE txt_Deallocate -END INTERFACE TxtFileDeallocate - -PUBLIC :: TxtFileDeallocate - -!---------------------------------------------------------------------------- -! Final@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE txt_final(obj) - TYPE(TxtFile_), INTENT(INOUT) :: obj - END SUBROUTINE txt_final -END INTERFACE diff --git a/src/modules/TxtFile/src/GetMethods.inc b/src/modules/TxtFile/src/GetMethods.inc deleted file mode 100644 index 01936a48a..000000000 --- a/src/modules/TxtFile/src/GetMethods.inc +++ /dev/null @@ -1,73 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! GetEchoUnit@GetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Get the echo units - -INTERFACE - MODULE PURE FUNCTION txt_getEchoUnit(obj) RESULT(ans) - CLASS(TxtFile_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION txt_getEchoUnit -END INTERFACE - -!---------------------------------------------------------------------------- -! getTotalRecords@GetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 2021-11-09 -! update: 2021-11-09 -! summary: Returns the total number of records in a file -! -! -!# Introduction -! -! This function returns the total number of records in a file -! If `ignoreComment=.TRUE.`, then the comments are ignored -! If `ignoreComment` is true, then `commentSymbol` should be given - -INTERFACE - MODULE FUNCTION txt_getTotalRecords(obj, ignoreComment, ignoreBlank, & - & commentSymbol) RESULT(Ans) - CLASS(TxtFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - INTEGER(I4B) :: ans - END FUNCTION txt_getTotalRecords -END INTERFACE - -!---------------------------------------------------------------------------- -! GetEchoStat@GetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Get the echo status - -INTERFACE - MODULE PURE FUNCTION txt_getEchoStat(obj) RESULT(ans) - CLASS(TxtFile_), INTENT(IN) :: obj - LOGICAL(LGT) :: ans - END FUNCTION txt_getEchoStat -END INTERFACE diff --git a/src/modules/TxtFile/src/ReadMethods.inc b/src/modules/TxtFile/src/ReadMethods.inc deleted file mode 100644 index 930eba2ec..000000000 --- a/src/modules/TxtFile/src/ReadMethods.inc +++ /dev/null @@ -1,292 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! ReadLine@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Read a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_read_Line(obj, val, iostat, iomsg, & - & ignoreComment, ignoreBlank, commentSymbol, separator ) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), INTENT(OUT) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: separator - END SUBROUTINE txt_read_Line -END INTERFACE - -!---------------------------------------------------------------------------- -! ReadLine@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Read a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_read_Lines(obj, val, iostat, iomsg, & - & ignoreComment, ignoreBlank, commentSymbol, separator ) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), ALLOCATABLE, INTENT(INOUT) :: val( : ) - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: separator - END SUBROUTINE txt_read_Lines -END INTERFACE - -!---------------------------------------------------------------------------- -! ReadLine@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Read a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_read_Char(obj, val, iostat, iomsg, & - & ignoreComment, ignoreBlank, commentSymbol, separator ) - CLASS(TxtFile_), INTENT(INOUT) :: obj - CHARACTER( LEN = * ), INTENT(OUT) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: separator - END SUBROUTINE txt_read_Char -END INTERFACE - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a scalar integer - -#define __SUBROUTINE_NAME__ txt_read_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a scalar real value - -#define __SUBROUTINE_NAME__ txt_read_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read an integer vector - -#define __SUBROUTINE_NAME__ txt_read_vec_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a intvector - -#define __SUBROUTINE_NAME__ txt_read_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a vector of intvector - -#define __SUBROUTINE_NAME__ txt_read_vec_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a real value vector - -#define __SUBROUTINE_NAME__ txt_read_vec_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a realvector - -#define __SUBROUTINE_NAME__ txt_read_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a vector of realvector - -#define __SUBROUTINE_NAME__ txt_read_vec_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read an integer matrix - -#define __SUBROUTINE_NAME__ txt_read_mat_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a real value vector - -#define __SUBROUTINE_NAME__ txt_read_mat_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - diff --git a/src/modules/TxtFile/src/SetMethods.inc b/src/modules/TxtFile/src/SetMethods.inc deleted file mode 100644 index e41b861fa..000000000 --- a/src/modules/TxtFile/src/SetMethods.inc +++ /dev/null @@ -1,47 +0,0 @@ -! 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 -! - - -!---------------------------------------------------------------------------- -! SetEchoStat@SetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Set the echo status - -INTERFACE - MODULE SUBROUTINE txt_setEchoStat(obj, bool) - CLASS(TxtFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), INTENT(IN) :: bool - END SUBROUTINE txt_setEchoStat -END INTERFACE - -!---------------------------------------------------------------------------- -! SetEchoUnit@SetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Set the echo units - -INTERFACE - MODULE SUBROUTINE txt_setEchoUnit(obj, unitno) - CLASS(TxtFile_), INTENT(INOUT) :: obj - INTEGER(I4B), INTENT(IN) :: unitno - END SUBROUTINE txt_setEchoUnit -END INTERFACE diff --git a/src/modules/TxtFile/src/TxtFile_Class.F90 b/src/modules/TxtFile/src/TxtFile_Class.F90 index 0e87d9a2e..596083660 100644 --- a/src/modules/TxtFile/src/TxtFile_Class.F90 +++ b/src/modules/TxtFile/src/TxtFile_Class.F90 @@ -26,8 +26,14 @@ MODULE TxtFile_Class USE FortranFile_Class IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = 'TxtFile_Class' +CHARACTER(*), PARAMETER :: modName = 'TxtFile_Class' INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: TxtFilePointer_ +PUBLIC :: TxtFile_ +PUBLIC :: TypeTxtFile +PUBLIC :: TxtFileInitiate +PUBLIC :: TxtFileDeallocate +PUBLIC :: TxtFileWrite !---------------------------------------------------------------------------- ! TxtFile_ @@ -46,126 +52,124 @@ MODULE TxtFile_Class PRIVATE LOGICAL(LGT) :: echostat = .FALSE. INTEGER(I4B) :: echounit = -1 - ! + CONTAINS PRIVATE - !! - !! @ConstructorMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: initiate => txt_initiate - PROCEDURE, PUBLIC, PASS(obj) :: Deallocate => txt_Deallocate + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => txt_initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => txt_Deallocate FINAL :: txt_final - !! - !! @EnquireMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: isValidRecord => txt_isValidRecord - !! - !! @SetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: setEchoStat => txt_setEchoStat - PROCEDURE, PUBLIC, PASS(obj) :: setEchoUnit => txt_setEchoUnit - !! - !! @GetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: getEchoStat => txt_getEchoStat - PROCEDURE, PUBLIC, PASS(obj) :: getEchoUnit => txt_getEchoUnit - PROCEDURE, PUBLIC, PASS(obj) :: getTotalRecords => txt_getTotalRecords - !! - !! @ReadMethods - !! - !! read strings and chars - PROCEDURE, PUBLIC, PASS(obj) :: readLine => txt_read_Line - PROCEDURE, PUBLIC, PASS(obj) :: readLines => txt_read_Lines - PROCEDURE, PASS(obj) :: readChar => txt_read_Char + + ! GET: + ! @EnquireMethods + PROCEDURE, PUBLIC, PASS(obj) :: IsValidRecord => txt_IsValidRecord + + ! SET: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(obj) :: SetEchoStat => txt_SetEchoStat + PROCEDURE, PUBLIC, PASS(obj) :: SetEchoUnit => txt_SetEchoUnit + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetEchoStat => txt_GetEchoStat + PROCEDURE, PUBLIC, PASS(obj) :: GetEchoUnit => txt_GetEchoUnit + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalRecords => txt_GetTotalRecords + + ! IO: + ! @ReadMethods + PROCEDURE, PUBLIC, PASS(obj) :: ReadLine => txt_read_Line + !! Read strings and chars + PROCEDURE, PUBLIC, PASS(obj) :: ReadLines => txt_read_Lines + !! Read strings and chars + PROCEDURE, PASS(obj) :: ReadChar => txt_read_Char !! scalars - PROCEDURE, PASS(obj) :: readInt8 => txt_read_Int8 - PROCEDURE, PASS(obj) :: readInt16 => txt_read_Int16 - PROCEDURE, PASS(obj) :: readInt32 => txt_read_Int32 - PROCEDURE, PASS(obj) :: readInt64 => txt_read_Int64 - PROCEDURE, PASS(obj) :: readReal32 => txt_read_Real32 - PROCEDURE, PASS(obj) :: readReal64 => txt_read_Real64 + PROCEDURE, PASS(obj) :: ReadInt8 => txt_read_Int8 + PROCEDURE, PASS(obj) :: ReadInt16 => txt_read_Int16 + PROCEDURE, PASS(obj) :: ReadInt32 => txt_read_Int32 + PROCEDURE, PASS(obj) :: ReadInt64 => txt_read_Int64 + PROCEDURE, PASS(obj) :: ReadReal32 => txt_read_Real32 + PROCEDURE, PASS(obj) :: ReadReal64 => txt_read_Real64 !! vectors - PROCEDURE, PASS(obj) :: readVecInt8 => txt_read_vec_Int8 - PROCEDURE, PASS(obj) :: readVecInt16 => txt_read_vec_Int16 - PROCEDURE, PASS(obj) :: readVecInt32 => txt_read_vec_Int32 - PROCEDURE, PASS(obj) :: readVecInt64 => txt_read_vec_Int64 - PROCEDURE, PASS(obj) :: readIntVector => txt_read_IntVector - PROCEDURE, PASS(obj) :: readVecIntVector => txt_read_vec_IntVector - PROCEDURE, PASS(obj) :: readVecReal32 => txt_read_vec_Real32 - PROCEDURE, PASS(obj) :: readVecReal64 => txt_read_vec_Real64 - PROCEDURE, PASS(obj) :: readRealVector => txt_read_RealVector - PROCEDURE, PASS(obj) :: readVecRealVector => txt_read_vec_RealVector + PROCEDURE, PASS(obj) :: ReadVecInt8 => txt_read_vec_Int8 + PROCEDURE, PASS(obj) :: ReadVecInt16 => txt_read_vec_Int16 + PROCEDURE, PASS(obj) :: ReadVecInt32 => txt_read_vec_Int32 + PROCEDURE, PASS(obj) :: ReadVecInt64 => txt_read_vec_Int64 + PROCEDURE, PASS(obj) :: ReadIntVector => txt_read_IntVector + PROCEDURE, PASS(obj) :: ReadVecIntVector => txt_read_vec_IntVector + PROCEDURE, PASS(obj) :: ReadVecReal32 => txt_read_vec_Real32 + PROCEDURE, PASS(obj) :: ReadVecReal64 => txt_read_vec_Real64 + PROCEDURE, PASS(obj) :: ReadRealVector => txt_read_RealVector + PROCEDURE, PASS(obj) :: ReadVecRealVector => txt_read_vec_RealVector !! matrix - PROCEDURE, PASS(obj) :: readMatReal32 => txt_read_Mat_Real32 - PROCEDURE, PASS(obj) :: readMatReal64 => txt_read_Mat_Real64 - PROCEDURE, PASS(obj) :: readMatInt8 => txt_read_Mat_Int8 - PROCEDURE, PASS(obj) :: readMatInt16 => txt_read_Mat_Int16 - PROCEDURE, PASS(obj) :: readMatInt32 => txt_read_Mat_Int32 - PROCEDURE, PASS(obj) :: readMatInt64 => txt_read_Mat_Int64 + PROCEDURE, PASS(obj) :: ReadMatReal32 => txt_read_Mat_Real32 + PROCEDURE, PASS(obj) :: ReadMatReal64 => txt_read_Mat_Real64 + PROCEDURE, PASS(obj) :: ReadMatInt8 => txt_read_Mat_Int8 + PROCEDURE, PASS(obj) :: ReadMatInt16 => txt_read_Mat_Int16 + PROCEDURE, PASS(obj) :: ReadMatInt32 => txt_read_Mat_Int32 + PROCEDURE, PASS(obj) :: ReadMatInt64 => txt_read_Mat_Int64 !! generic - GENERIC, PUBLIC :: read => & - & readLine, readLines, readChar, & - & readInt8, readInt16, readInt32, readInt64, & - & readReal32, readReal64, & - & readVecInt8, readVecInt16, readVecInt32, readVecInt64, & - & readIntVector, readVecIntVector, & - & readVecReal32, readVecReal64, & - & readRealVector, readVecRealVector, & - & readMatInt8, readMatInt16, readMatInt32, readMatInt64, & - & readMatReal32, readMatReal64 - !! - !! @WriteMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: convertMarkdownToSource => & - & txt_convertMarkDownToSource - !! - PROCEDURE, PUBLIC, PASS(obj) :: writeBlank => txt_write_Blank - PROCEDURE, PUBLIC, PASS(obj) :: nextRow => txt_write_Blank - PROCEDURE, PUBLIC, PASS(obj) :: writeLine => txt_write_Line - PROCEDURE, PUBLIC, PASS(obj) :: writeLines => txt_write_Lines - PROCEDURE, PASS(obj) :: writeChar => txt_write_Char + GENERIC, PUBLIC :: Read => & + & ReadLine, ReadLines, ReadChar, & + & ReadInt8, ReadInt16, ReadInt32, ReadInt64, & + & ReadReal32, ReadReal64, & + & ReadVecInt8, ReadVecInt16, ReadVecInt32, ReadVecInt64, & + & ReadIntVector, ReadVecIntVector, & + & ReadVecReal32, ReadVecReal64, & + & ReadRealVector, ReadVecRealVector, & + & ReadMatInt8, ReadMatInt16, ReadMatInt32, ReadMatInt64, & + & ReadMatReal32, ReadMatReal64 + + ! IO: + ! @WriteMethods + PROCEDURE, PUBLIC, PASS(obj) :: ConvertMarkdownToSource => & + & txt_ConvertMarkDownToSource + PROCEDURE, PUBLIC, PASS(obj) :: WriteBlank => txt_write_Blank + PROCEDURE, PUBLIC, PASS(obj) :: nextRow => txt_Write_Blank + PROCEDURE, PUBLIC, PASS(obj) :: WriteLine => txt_write_Line + PROCEDURE, PUBLIC, PASS(obj) :: WriteLines => txt_write_Lines + PROCEDURE, PASS(obj) :: WriteChar => txt_write_Char !! scalars - PROCEDURE, PASS(obj) :: writeInt8 => txt_write_Int8 - PROCEDURE, PASS(obj) :: writeInt16 => txt_write_Int16 - PROCEDURE, PASS(obj) :: writeInt32 => txt_write_Int32 - PROCEDURE, PASS(obj) :: writeInt64 => txt_write_Int64 - PROCEDURE, PASS(obj) :: writeReal32 => txt_write_Real32 - PROCEDURE, PASS(obj) :: writeReal64 => txt_write_Real64 + PROCEDURE, PASS(obj) :: WriteInt8 => txt_write_Int8 + PROCEDURE, PASS(obj) :: WriteInt16 => txt_write_Int16 + PROCEDURE, PASS(obj) :: WriteInt32 => txt_write_Int32 + PROCEDURE, PASS(obj) :: WriteInt64 => txt_write_Int64 + PROCEDURE, PASS(obj) :: WriteReal32 => txt_write_Real32 + PROCEDURE, PASS(obj) :: WriteReal64 => txt_write_Real64 !! vectors - PROCEDURE, PASS(obj) :: writeVecInt8 => txt_write_vec_Int8 - PROCEDURE, PASS(obj) :: writeVecInt16 => txt_write_vec_Int16 - PROCEDURE, PASS(obj) :: writeVecInt32 => txt_write_vec_Int32 - PROCEDURE, PASS(obj) :: writeVecInt64 => txt_write_vec_Int64 - PROCEDURE, PASS(obj) :: writeIntVector => txt_write_IntVector - PROCEDURE, PASS(obj) :: writeVecIntVector => txt_write_vec_IntVector - PROCEDURE, PASS(obj) :: writeVecReal32 => txt_write_vec_Real32 - PROCEDURE, PASS(obj) :: writeVecReal64 => txt_write_vec_Real64 - PROCEDURE, PASS(obj) :: writeRealVector => txt_write_RealVector - PROCEDURE, PASS(obj) :: writeVecRealVector => txt_write_vec_RealVector + PROCEDURE, PASS(obj) :: WriteVecInt8 => txt_write_vec_Int8 + PROCEDURE, PASS(obj) :: WriteVecInt16 => txt_write_vec_Int16 + PROCEDURE, PASS(obj) :: WriteVecInt32 => txt_write_vec_Int32 + PROCEDURE, PASS(obj) :: WriteVecInt64 => txt_write_vec_Int64 + PROCEDURE, PASS(obj) :: WriteIntVector => txt_write_IntVector + PROCEDURE, PASS(obj) :: WriteVecIntVector => txt_write_vec_IntVector + PROCEDURE, PASS(obj) :: WriteVecReal32 => txt_write_vec_Real32 + PROCEDURE, PASS(obj) :: WriteVecReal64 => txt_write_vec_Real64 + PROCEDURE, PASS(obj) :: WriteRealVector => txt_write_RealVector + PROCEDURE, PASS(obj) :: WriteVecRealVector => txt_write_vec_RealVector !! matrix - PROCEDURE, PASS(obj) :: writeMatReal32 => txt_write_Mat_Real32 - PROCEDURE, PASS(obj) :: writeMatReal64 => txt_write_Mat_Real64 - PROCEDURE, PASS(obj) :: writeMatInt8 => txt_write_Mat_Int8 - PROCEDURE, PASS(obj) :: writeMatInt16 => txt_write_Mat_Int16 - PROCEDURE, PASS(obj) :: writeMatInt32 => txt_write_Mat_Int32 - PROCEDURE, PASS(obj) :: writeMatInt64 => txt_write_Mat_Int64 + PROCEDURE, PASS(obj) :: WriteMatReal32 => txt_write_Mat_Real32 + PROCEDURE, PASS(obj) :: WriteMatReal64 => txt_write_Mat_Real64 + PROCEDURE, PASS(obj) :: WriteMatInt8 => txt_write_Mat_Int8 + PROCEDURE, PASS(obj) :: WriteMatInt16 => txt_write_Mat_Int16 + PROCEDURE, PASS(obj) :: WriteMatInt32 => txt_write_Mat_Int32 + PROCEDURE, PASS(obj) :: WriteMatInt64 => txt_write_Mat_Int64 !! generic - GENERIC, PUBLIC :: write => & - & writeBlank, & - & writeLine, writeLines, writeChar, & - & writeInt8, writeInt16, writeInt32, writeInt64, & - & writeVecInt8, writeVecInt16, writeVecInt32, writeVecInt64, & - & writeMatInt8, writeMatInt16, writeMatInt32, writeMatInt64, & - & writeIntVector, writeVecIntVector, & - & writeReal32, writeReal64, & - & writeVecReal32, writeVecReal64, & - & writeRealVector, writeVecRealVector, & - & writeMatReal32, writeMatReal64 + GENERIC, PUBLIC :: Write => & + & WriteBlank, & + & WriteLine, WriteLines, WriteChar, & + & WriteInt8, WriteInt16, WriteInt32, WriteInt64, & + & WriteVecInt8, WriteVecInt16, WriteVecInt32, WriteVecInt64, & + & WriteMatInt8, WriteMatInt16, WriteMatInt32, WriteMatInt64, & + & WriteIntVector, WriteVecIntVector, & + & WriteReal32, WriteReal64, & + & WriteVecReal32, WriteVecReal64, & + & WriteRealVector, WriteVecRealVector, & + & WriteMatReal32, WriteMatReal64 END TYPE TxtFile_ -PUBLIC :: TxtFile_ - -TYPE(TxtFile_), PUBLIC, PARAMETER :: TypeTxtFile = TxtFile_() +TYPE(TxtFile_), PARAMETER :: TypeTxtFile = TxtFile_() !---------------------------------------------------------------------------- ! TxtFilePointer @@ -175,13 +179,808 @@ MODULE TxtFile_Class CLASS(TxtFile_), POINTER :: ptr => NULL() END TYPE -PUBLIC :: TxtFilePointer_ +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Initiate the txt file + +INTERFACE TxtFileInitiate + MODULE SUBROUTINE txt_initiate(obj, filename, unit, status, access, form, & + & position, action, pad, recl, comment, separator, delimiter) + CLASS(TxtFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: filename + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unit + !! User specified unit number, it should not be `stdout, stdin, stderr` + CHARACTER(*), OPTIONAL, INTENT(IN) :: status + !! OLD, NEW, SCRATCH, REPLACE, UNKNOWN + !! If UNKNOWN then we use REPLACE + !! Default is REPLACE + CHARACTER(*), OPTIONAL, INTENT(IN) :: access + !! DIRECT, SEQUENTIAL, STREAM + !! Default is SEQUENTIAL + CHARACTER(*), OPTIONAL, INTENT(IN) :: form + !! FORMATTED, UNFORMATTED + !! Default is FORMATTED + CHARACTER(*), OPTIONAL, INTENT(IN) :: position + !! REWIND, APPEND, ASIS + !! Default is ASIS + CHARACTER(*), OPTIONAL, INTENT(IN) :: action + !! READ, WRITE, READWRITE + CHARACTER(*), OPTIONAL, INTENT(IN) :: pad + !! YES, NO + !! Default is YES + INTEGER(I4B), OPTIONAL, INTENT(IN) :: recl + CHARACTER(*), OPTIONAL, INTENT(IN) :: comment + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + CHARACTER(*), OPTIONAL, INTENT(IN) :: delimiter + END SUBROUTINE txt_initiate +END INTERFACE TxtFileInitiate + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Deallocate the data + +INTERFACE TxtFileDeallocate + MODULE SUBROUTINE txt_Deallocate(obj, Delete) + CLASS(TxtFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete + END SUBROUTINE txt_Deallocate +END INTERFACE TxtFileDeallocate + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE txt_final(obj) + TYPE(TxtFile_), INTENT(INOUT) :: obj + END SUBROUTINE txt_final +END INTERFACE + +!---------------------------------------------------------------------------- +! isValidRecord@EnquireMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION txt_isValidRecord(obj, aline, ignoreComment, ignoreBlank, & + & commentSymbol) RESULT(Ans) + CLASS(TxtFile_), INTENT(IN) :: obj + TYPE(String), INTENT(IN) :: aline + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + LOGICAL(LGT) :: ans + END FUNCTION txt_isValidRecord +END INTERFACE + +!---------------------------------------------------------------------------- +! SetEchoStat@SetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Set the echo status + +INTERFACE + MODULE SUBROUTINE txt_setEchoStat(obj, bool) + CLASS(TxtFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: bool + END SUBROUTINE txt_setEchoStat +END INTERFACE + +!---------------------------------------------------------------------------- +! SetEchoUnit@SetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Set the echo units + +INTERFACE + MODULE SUBROUTINE txt_setEchoUnit(obj, unitno) + CLASS(TxtFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: unitno + END SUBROUTINE txt_setEchoUnit +END INTERFACE + +!---------------------------------------------------------------------------- +! GetEchoUnit@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Get the echo units + +INTERFACE + MODULE PURE FUNCTION txt_getEchoUnit(obj) RESULT(ans) + CLASS(TxtFile_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION txt_getEchoUnit +END INTERFACE + +!---------------------------------------------------------------------------- +! getTotalRecords@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2021-11-09 +! update: 2021-11-09 +! summary: Returns the total number of records in a file +! +! +!# Introduction +! +! This function returns the total number of records in a file +! If `ignoreComment=.TRUE.`, then the comments are ignored +! If `ignoreComment` is true, then `commentSymbol` should be given + +INTERFACE + MODULE FUNCTION txt_getTotalRecords(obj, ignoreComment, ignoreBlank, & + & commentSymbol) RESULT(Ans) + CLASS(TxtFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + INTEGER(I4B) :: ans + END FUNCTION txt_getTotalRecords +END INTERFACE + +!---------------------------------------------------------------------------- +! GetEchoStat@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Get the echo status + +INTERFACE + MODULE PURE FUNCTION txt_getEchoStat(obj) RESULT(ans) + CLASS(TxtFile_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + END FUNCTION txt_getEchoStat +END INTERFACE + +!---------------------------------------------------------------------------- +! ReadLine@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Read a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_read_Line(obj, val, iostat, iomsg, & + & ignoreComment, ignoreBlank, commentSymbol, separator) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(OUT) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + END SUBROUTINE txt_read_Line +END INTERFACE + +!---------------------------------------------------------------------------- +! ReadLine@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Read a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_read_Lines(obj, val, iostat, iomsg, & + & ignoreComment, ignoreBlank, commentSymbol, separator) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), ALLOCATABLE, INTENT(INOUT) :: val(:) + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + END SUBROUTINE txt_read_Lines +END INTERFACE + +!---------------------------------------------------------------------------- +! ReadLine@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Read a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_read_Char(obj, val, iostat, iomsg, & + & ignoreComment, ignoreBlank, commentSymbol, separator) + CLASS(TxtFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(OUT) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + END SUBROUTINE txt_read_Char +END INTERFACE + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a scalar integer + +#define __SUBROUTINE_NAME__ txt_read_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a scalar real value + +#define __SUBROUTINE_NAME__ txt_read_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read an integer vector + +#define __SUBROUTINE_NAME__ txt_read_vec_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a intvector + +#define __SUBROUTINE_NAME__ txt_read_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a vector of intvector + +#define __SUBROUTINE_NAME__ txt_read_vec_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a real value vector + +#define __SUBROUTINE_NAME__ txt_read_vec_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a realvector + +#define __SUBROUTINE_NAME__ txt_read_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a vector of realvector + +#define __SUBROUTINE_NAME__ txt_read_vec_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read an integer matrix + +#define __SUBROUTINE_NAME__ txt_read_mat_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a real value vector + +#define __SUBROUTINE_NAME__ txt_read_mat_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! ConvertMarkdownToSource@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2021-11-07 +! update: 2021-11-07 +! summary: Reads a markdown file and converts it into the source file + +INTERFACE + MODULE SUBROUTINE txt_convertMarkdownToSource(obj, outfile, lang) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(TxtFile_), INTENT(INOUT) :: outfile + CHARACTER(*), OPTIONAL, INTENT(IN) :: lang + END SUBROUTINE txt_convertMarkdownToSource +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Blank(obj) + CLASS(TxtFile_), INTENT(INOUT) :: obj + !! YES or NO + END SUBROUTINE txt_write_Blank +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Line(obj, val, iostat, iomsg, advance) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + CHARACTER(*), OPTIONAL, INTENT(IN) :: advance + !! YES or NO + END SUBROUTINE txt_write_Line +END INTERFACE + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Line +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Lines(obj, val, iostat, iomsg, advance) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: val(:) + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + CHARACTER(*), OPTIONAL, INTENT(IN) :: advance + !! YES, NO + END SUBROUTINE txt_write_Lines +END INTERFACE + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Lines +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Char(obj, val, iostat, iomsg, & + & advance) + CLASS(TxtFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + CHARACTER(*), OPTIONAL, INTENT(IN) :: advance + !! YES, NO + END SUBROUTINE txt_write_Char +END INTERFACE + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Char +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! Write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write an integer + +#define __SUBROUTINE_NAME__ txt_write_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Int8, txt_write_Int16, txt_write_Int32, & + & txt_write_Int64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a real value + +#define __SUBROUTINE_NAME__ txt_write_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Real32, txt_write_Real64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! Write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write an integer vector + +#define __SUBROUTINE_NAME__ txt_write_vec_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_Int8, & + & txt_write_vec_Int16, & + & txt_write_vec_Int32, & + & txt_write_vec_Int64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a intvector + +#define __SUBROUTINE_NAME__ txt_write_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_IntVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a vector of intvector + +#define __SUBROUTINE_NAME__ txt_write_vec_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_IntVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a real value vector + +#define __SUBROUTINE_NAME__ txt_write_vec_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_Real32, txt_write_vec_Real64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a RealVector + +#define __SUBROUTINE_NAME__ txt_write_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_RealVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a vector of RealVector + +#define __SUBROUTINE_NAME__ txt_write_vec_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_RealVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! Write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write an integer matrix + +#define __SUBROUTINE_NAME__ txt_write_mat_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_mat_Int8, & + & txt_write_mat_Int16, & + & txt_write_mat_Int32, & + & txt_write_mat_Int64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a real value vector + +#define __SUBROUTINE_NAME__ txt_write_mat_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ -#include "./ConstructorMethods.inc" -#include "./EnquireMethods.inc" -#include "./SetMethods.inc" -#include "./GetMethods.inc" -#include "./ReadMethods.inc" -#include "./WriteMethods.inc" +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_mat_Real32, & + & txt_write_mat_Real64 +END INTERFACE TxtFileWrite END MODULE TxtFile_Class diff --git a/src/modules/TxtFile/src/WriteMethods.inc b/src/modules/TxtFile/src/WriteMethods.inc deleted file mode 100644 index 7caf2546a..000000000 --- a/src/modules/TxtFile/src/WriteMethods.inc +++ /dev/null @@ -1,381 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! ConvertMarkdownToSource@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 2021-11-07 -! update: 2021-11-07 -! summary: Reads a markdown file and converts it into the source file - -INTERFACE - MODULE SUBROUTINE txt_convertMarkdownToSource(obj, outfile, lang) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(TxtFile_), INTENT(INOUT) :: outfile - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: lang - END SUBROUTINE txt_convertMarkdownToSource -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Blank(obj) - CLASS(TxtFile_), INTENT(INOUT) :: obj - !! YES or NO - END SUBROUTINE txt_write_Blank -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Line(obj, val, iostat, iomsg, advance) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), INTENT(IN) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: advance - !! YES or NO - END SUBROUTINE txt_write_Line -END INTERFACE - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Line -END INTERFACE TxtFileWrite - -PUBLIC :: TxtFileWrite - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Lines(obj, val, iostat, iomsg, advance) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), INTENT(IN) :: val(:) - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: advance - !! YES, NO - END SUBROUTINE txt_write_Lines -END INTERFACE - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Lines -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Char(obj, val, iostat, iomsg, & - & advance) - CLASS(TxtFile_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: advance - !! YES, NO - END SUBROUTINE txt_write_Char -END INTERFACE - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Char -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! Write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write an integer - -#define __SUBROUTINE_NAME__ txt_write_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Int8, txt_write_Int16, txt_write_Int32, & - & txt_write_Int64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a real value - -#define __SUBROUTINE_NAME__ txt_write_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Real32, txt_write_Real64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! Write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write an integer vector - -#define __SUBROUTINE_NAME__ txt_write_vec_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_Int8, & - & txt_write_vec_Int16, & - & txt_write_vec_Int32, & - & txt_write_vec_Int64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a intvector - -#define __SUBROUTINE_NAME__ txt_write_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_IntVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a vector of intvector - -#define __SUBROUTINE_NAME__ txt_write_vec_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_IntVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a real value vector - -#define __SUBROUTINE_NAME__ txt_write_vec_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_Real32, txt_write_vec_Real64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a RealVector - -#define __SUBROUTINE_NAME__ txt_write_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_RealVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a vector of RealVector - -#define __SUBROUTINE_NAME__ txt_write_vec_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_RealVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! Write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write an integer matrix - -#define __SUBROUTINE_NAME__ txt_write_mat_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_mat_Int8, & - & txt_write_mat_Int16, & - & txt_write_mat_Int32, & - & txt_write_mat_Int64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a real value vector - -#define __SUBROUTINE_NAME__ txt_write_mat_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_mat_Real32, & - & txt_write_mat_Real64 -END INTERFACE TxtFileWrite - diff --git a/src/modules/UserFunction/src/UseFunction.toml b/src/modules/UserFunction/src/UseFunction.toml new file mode 100644 index 000000000..eae18f084 --- /dev/null +++ b/src/modules/UserFunction/src/UseFunction.toml @@ -0,0 +1,16 @@ +[userFunction] +returnType = "Scalar" +# returnType = "Vector" +# returnType = "Matrix" +argType = "Space" +# argType = "Constant" +# argType = "Space" +# argType = "Time" +# argType = "SpaceTime" +numArgs = 3 +numReturns = 1 +luaScript = "./hello.lua" +luaFunctionName="hello" +scalarValue = 1.0 +vectorValue = [1.0, 2.0, 3.0] +matrixValue = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]] diff --git a/src/modules/UserFunction/src/UserFunction_Class.F90 b/src/modules/UserFunction/src/UserFunction_Class.F90 index b86b81b34..c4670a3c7 100644 --- a/src/modules/UserFunction/src/UserFunction_Class.F90 +++ b/src/modules/UserFunction/src/UserFunction_Class.F90 @@ -16,13 +16,17 @@ MODULE UserFunction_Class USE GlobalData +USE BaseType +USE String_Class, ONLY: String USE FPL, ONLY: ParameterList_ USE HDF5File_Class +USE TxtFile_Class USE ExceptionHandler_Class, ONLY: e +USE tomlf, ONLY: toml_table IMPLICIT NONE PRIVATE -!! CHARACTER(*), PARAMETER :: modName = "UserFunction_Class" +CHARACTER(*), PARAMETER :: myprefix = "UserFunction" CHARACTER(*), PARAMETER :: NAME_RETURN_TYPE(3) = & & [ & & "Scalar", & @@ -37,49 +41,103 @@ MODULE UserFunction_Class & "SpaceTime ", & & "SolutionDependent" & & ] +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_SCALAR = 1 +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_VECTOR = 3 +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_MATRIX = 6 +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_CONSTANT = 0 +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_SPACE = 3 +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_TIME = 1 +INTEGER(I4B), PARAMETER :: DEFAULT_NUM_ARG_SPACETIME = 4 + +PUBLIC :: UserFunction_ +PUBLIC :: UserFunctionGetReturnType +PUBLIC :: UserFunctionGetArgType +PUBLIC :: SetUserFunctionParam +PUBLIC :: UserFunctionImportFromToml +PUBLIC :: UserFunctionImportParamFromToml +PUBLIC :: UserFunctionPointer_ !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-20 +! summary: User defined function + TYPE :: UserFunction_ + PRIVATE LOGICAL(LGT) :: isInitiated = .FALSE. LOGICAL(LGT) :: isUserFunctionSet = .FALSE. + LOGICAL(LGT) :: isLuaScript = .FALSE. + TYPE(String) :: luaScript + TYPE(String) :: luaFunctionName INTEGER(I4B) :: returnType = 0 INTEGER(I4B) :: argType = 0 + INTEGER(I4B) :: numArgs = 0 + !! Number of arguments + !! number of args is 1 for scalar argType scalar + INTEGER(I4B) :: numReturns = 0 + !! Number of return types + !! number of return type is 1 for scalar return + INTEGER(I4B) :: returnShape(2) = 0 + !! Shape of return + !! Only used when returnType is matrix REAL(DFP) :: scalarValue = 0.0 + !! Scalar constant value REAL(DFP), ALLOCATABLE :: vectorValue(:) + !! Vector constant value REAL(DFP), ALLOCATABLE :: matrixValue(:, :) - CLASS(UserFunction_), POINTER :: userFunction => NULL() + !! Matrix constant value + PROCEDURE(iface_ScalarFunction), POINTER, NOPASS :: scalarFunction => & + & NULL() + !! Scalar function pointer + PROCEDURE(iface_VectorFunction), POINTER, NOPASS :: vectorFunction => & + & NULL() + !! vector function pointer + PROCEDURE(iface_MatrixFunction), POINTER, NOPASS :: matrixFunction => & + & NULL() + !! matrix function pointer CONTAINS - PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & - & auf_checkEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & auf_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => auf_Deallocate FINAL :: auf_Final PROCEDURE, PUBLIC, PASS(obj) :: Initiate => auf_Initiate - PROCEDURE, PUBLIC, PASS(obj) :: Set1 => auf_Set1 - PROCEDURE, PUBLIC, PASS(obj) :: Set2 => auf_Set2 - GENERIC, PUBLIC :: Set => Set1, Set2 - PROCEDURE, PUBLIC, PASS(obj) :: getScalarValue => auf_getScalarValue - PROCEDURE, PUBLIC, PASS(obj) :: getVectorValue => auf_getVectorValue - PROCEDURE, PUBLIC, PASS(obj) :: getMatrixValue => auf_getMatrixValue - GENERIC, PUBLIC :: get => getScalarValue, getVectorValue, getMatrixValue - PROCEDURE, PUBLIC, PASS(obj) :: getArgType => auf_getArgType - PROCEDURE, PUBLIC, PASS(obj) :: getReturnType => auf_getReturnType + PROCEDURE, PUBLIC, PASS(obj) :: Set => auf_Set1 + PROCEDURE, PUBLIC, PASS(obj) :: GetScalarValue => auf_GetScalarValue + PROCEDURE, PUBLIC, PASS(obj) :: GetVectorValue => auf_GetVectorValue + PROCEDURE, PUBLIC, PASS(obj) :: GetMatrixValue => auf_GetMatrixValue + GENERIC, PUBLIC :: Get => GetScalarValue, GetVectorValue, GetMatrixValue + PROCEDURE, PUBLIC, PASS(obj) :: GetArgType => auf_GetArgType + PROCEDURE, PUBLIC, PASS(obj) :: GetReturnType => auf_GetReturnType PROCEDURE, PUBLIC, PASS(obj) :: Display => auf_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => auf_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => auf_Export + PROCEDURE, PASS(obj) :: ImportFromToml1 => auf_ImportFromToml1 + PROCEDURE, PASS(obj) :: ImportFromToml2 => auf_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & + & ImportFromToml2 + !! Import abstract kernel from toml + PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & + & auf_ImportParamFromToml END TYPE UserFunction_ -PUBLIC :: UserFunction_ +!---------------------------------------------------------------------------- +! UserFunctionPointer_ +!---------------------------------------------------------------------------- + +TYPE :: UserFunctionPointer_ + CLASS(UserFunction_), POINTER :: ptr => NULL() +END TYPE UserFunctionPointer_ !---------------------------------------------------------------------------- -! getReturnTypeFromName@ConstructorMethods +! GetReturnTypeFromName@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 27 Oct 2021 -! summary: Returns the Integer corresponding to name +! summary: Returns the Integer number for given return type name (String) INTERFACE MODULE PURE FUNCTION UserFunctionGetReturnType(name) RESULT(Ans) @@ -88,8 +146,6 @@ MODULE PURE FUNCTION UserFunctionGetReturnType(name) RESULT(Ans) END FUNCTION UserFunctionGetReturnType END INTERFACE -PUBLIC :: UserFunctionGetReturnType - !---------------------------------------------------------------------------- ! etArgTypeFromName@ConstructorMethods !---------------------------------------------------------------------------- @@ -105,8 +161,6 @@ MODULE PURE FUNCTION UserFunctionGetArgType(name) RESULT(Ans) END FUNCTION UserFunctionGetArgType END INTERFACE -PUBLIC :: UserFunctionGetArgType - !---------------------------------------------------------------------------- ! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -131,22 +185,34 @@ END SUBROUTINE auf_CheckEssentialParam ! summary: Sets user funciton parameter INTERFACE - MODULE SUBROUTINE setUserFunctionParam(param, returnType, argType) + MODULE SUBROUTINE SetUserFunctionParam(param, returnType, argType, & + & numArgs, numReturns, luaScript, luaFunctionName, returnShape) TYPE(ParameterList_), INTENT(INOUT) :: param INTEGER(I4B), INTENT(IN) :: returnType + !! Scalar, Vector, Matrix INTEGER(I4B), INTENT(IN) :: argType - END SUBROUTINE setUserFunctionParam + !! Constant, Space, Time, SpaceTime + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numArgs + !! number of argument + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numReturns + !! number of returns + CHARACTER(*), OPTIONAL, INTENT(IN) :: luaScript + !! lua script + CHARACTER(*), OPTIONAL, INTENT(IN) :: luaFunctionName + !! lua function name + INTEGER(I4B), OPTIONAL, INTENT(IN) :: returnShape(2) + !! Shape of return type + !! Only used when returnType is Matrix + END SUBROUTINE SetUserFunctionParam END INTERFACE -PUBLIC :: setUserFunctionParam - !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 26 Oct 2021 -! summary: Deallocate the data in [[Userfunction_]] +! summary: Deallocate the data in UserFunction. INTERFACE MODULE SUBROUTINE auf_Deallocate(obj) @@ -160,7 +226,7 @@ END SUBROUTINE auf_Deallocate !> authors: Vikas Sharma, Ph. D. ! date: 26 Oct 2021 -! summary: Deallocate the data in [[Userfunction_]] +! summary: Deallocate the data in UserFunction. INTERFACE MODULE SUBROUTINE auf_Final(obj) @@ -177,46 +243,12 @@ END SUBROUTINE auf_Final ! summary: Initiate the user function INTERFACE - MODULE SUBROUTINE auf_Initiate(obj, argType, returnType, param) + MODULE SUBROUTINE auf_Initiate(obj, param) CLASS(UserFunction_), INTENT(INOUT) :: obj - INTEGER(I4B), INTENT(IN) :: argType - INTEGER(I4B), INTENT(IN) :: returnType - TYPE(ParameterList_), OPTIONAL, INTENT(IN) :: param + TYPE(ParameterList_), INTENT(IN) :: param END SUBROUTINE auf_Initiate END INTERFACE -!---------------------------------------------------------------------------- -! Set@SetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 26 Oct 2021 -! summary: Sets the user function - -INTERFACE - MODULE SUBROUTINE auf_Set1(obj, anotherObj) - CLASS(UserFunction_), INTENT(INOUT) :: obj - CLASS(UserFunction_), TARGET, INTENT(IN) :: anotherobj - END SUBROUTINE auf_Set1 -END INTERFACE - -!---------------------------------------------------------------------------- -! Set@SetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 26 Oct 2021 -! summary: Sets the user function - -INTERFACE - MODULE SUBROUTINE auf_Set2(obj, scalarValue, vectorValue, matrixValue) - CLASS(UserFunction_), INTENT(INOUT) :: obj - REAL(DFP), OPTIONAL, INTENT(IN) :: scalarValue - REAL(DFP), OPTIONAL, INTENT(IN) :: vectorValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: matrixValue(:, :) - END SUBROUTINE auf_Set2 -END INTERFACE - !---------------------------------------------------------------------------- ! Get@GetMethods !---------------------------------------------------------------------------- @@ -226,11 +258,11 @@ END SUBROUTINE auf_Set2 ! summary: Returns the scalar value INTERFACE - MODULE RECURSIVE SUBROUTINE auf_getScalarValue(obj, val, args) + MODULE RECURSIVE SUBROUTINE auf_GetScalarValue(obj, val, args) CLASS(UserFunction_), INTENT(INOUT) :: obj REAL(DFP), INTENT(INOUT) :: val REAL(DFP), OPTIONAL, INTENT(IN) :: args(:) - END SUBROUTINE auf_getScalarValue + END SUBROUTINE auf_GetScalarValue END INTERFACE !---------------------------------------------------------------------------- @@ -242,11 +274,11 @@ END SUBROUTINE auf_getScalarValue ! summary: Returns the vector value INTERFACE - MODULE RECURSIVE SUBROUTINE auf_getVectorValue(obj, val, args) + MODULE RECURSIVE SUBROUTINE auf_GetVectorValue(obj, val, args) CLASS(UserFunction_), INTENT(INOUT) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: val(:) REAL(DFP), OPTIONAL, INTENT(IN) :: args(:) - END SUBROUTINE auf_getVectorValue + END SUBROUTINE auf_GetVectorValue END INTERFACE !---------------------------------------------------------------------------- @@ -258,15 +290,15 @@ END SUBROUTINE auf_getVectorValue ! summary: Returns the Matrix value INTERFACE - MODULE RECURSIVE SUBROUTINE auf_getMatrixValue(obj, val, args) + MODULE RECURSIVE SUBROUTINE auf_GetMatrixValue(obj, val, args) CLASS(UserFunction_), INTENT(INOUT) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: val(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: args(:) - END SUBROUTINE auf_getMatrixValue + END SUBROUTINE auf_GetMatrixValue END INTERFACE !---------------------------------------------------------------------------- -! getArgType@GetMethods +! GetArgType@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -274,14 +306,14 @@ END SUBROUTINE auf_getMatrixValue ! summary: Returns the argument type INTERFACE - MODULE PURE FUNCTION auf_getArgType(obj) RESULT(ans) + MODULE PURE FUNCTION auf_GetArgType(obj) RESULT(ans) CLASS(UserFunction_), INTENT(IN) :: obj INTEGER(I4B) :: ans - END FUNCTION auf_getArgType + END FUNCTION auf_GetArgType END INTERFACE !---------------------------------------------------------------------------- -! getReturnType@GetMethods +! GetReturnType@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -289,16 +321,20 @@ END FUNCTION auf_getArgType ! summary: Returns the return type INTERFACE - MODULE PURE FUNCTION auf_getReturnType(obj) RESULT(ans) + MODULE PURE FUNCTION auf_GetReturnType(obj) RESULT(ans) CLASS(UserFunction_), INTENT(IN) :: obj INTEGER(I4B) :: ans - END FUNCTION auf_getReturnType + END FUNCTION auf_GetReturnType END INTERFACE !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-20 +! summary: Display the content of UserFunction + INTERFACE MODULE SUBROUTINE auf_Display(obj, msg, unitNo) CLASS(UserFunction_), INTENT(IN) :: obj @@ -311,6 +347,10 @@ END SUBROUTINE auf_Display ! Import@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-20 +! summary: Import data from HDF5File + INTERFACE MODULE SUBROUTINE auf_Import(obj, hdf5, group) CLASS(UserFunction_), INTENT(INOUT) :: obj @@ -319,10 +359,64 @@ MODULE SUBROUTINE auf_Import(obj, hdf5, group) END SUBROUTINE auf_Import END INTERFACE +!---------------------------------------------------------------------------- +! ImportParamFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param by reading the toml table + +INTERFACE UserFunctionImportParamFromToml + MODULE SUBROUTINE auf_ImportParamFromToml(obj, param, table) + CLASS(UserFunction_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE auf_ImportParamFromToml +END INTERFACE UserFunctionImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE UserFunctionImportFromToml + MODULE SUBROUTINE auf_ImportFromToml1(obj, table) + CLASS(UserFunction_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE auf_ImportFromToml1 +END INTERFACE UserFunctionImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE UserFunctionImportFromToml + MODULE SUBROUTINE auf_ImportFromToml2(obj, tomlName, afile, & + & filename, printToml) + CLASS(UserFunction_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE auf_ImportFromToml2 +END INTERFACE UserFunctionImportFromToml + !---------------------------------------------------------------------------- ! Export@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-20 +! summary: Export data to HDF5File + INTERFACE MODULE SUBROUTINE auf_Export(obj, hdf5, group) CLASS(UserFunction_), INTENT(IN) :: obj @@ -335,4 +429,156 @@ END SUBROUTINE auf_Export ! !---------------------------------------------------------------------------- +CONTAINS + +!---------------------------------------------------------------------------- +! Set@SetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 26 Oct 2021 +! summary: Sets the user function + +SUBROUTINE auf_Set1(obj, scalarValue, vectorValue, matrixValue, & + & luaScript, luaFunctionName, scalarFunction, vectorFunction, & + & matrixFunction) + USE BaseMethod, ONLY: Reallocate, tostring + CLASS(UserFunction_), INTENT(INOUT) :: obj + REAL(DFP), OPTIONAL, INTENT(IN) :: scalarValue + REAL(DFP), OPTIONAL, INTENT(IN) :: vectorValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: matrixValue(:, :) + CHARACTER(*), OPTIONAL, INTENT(IN) :: luaScript + CHARACTER(*), OPTIONAL, INTENT(IN) :: luaFunctionName + PROCEDURE(iface_ScalarFunction), POINTER, OPTIONAL, INTENT(IN) :: & + & scalarFunction + PROCEDURE(iface_VectorFunction), POINTER, OPTIONAL, INTENT(IN) :: & + & vectorFunction + PROCEDURE(iface_MatrixFunction), POINTER, OPTIONAL, INTENT(IN) :: & + & matrixFunction + + ! Internal variables + CHARACTER(*), PARAMETER :: myName = "auf_Set()" + LOGICAL(LGT) :: isNotOK + INTEGER(I4B) :: tsize, myshape(2) + +#ifdef DEBUG_VER + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Set()') +#endif + + isNotOK = .NOT. obj%isInitiated + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj is not initiated.') + RETURN + END IF + + IF (PRESENT(scalarValue)) THEN + isNotOK = (obj%argType .NE. Constant) .OR. (obj%returnType .NE. Scalar) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%argType is NOT Constant '// & + & ' or UserFunction_::obj%returnType is not Scalar') + RETURN + END IF + obj%scalarValue = scalarValue + END IF + + IF (PRESENT(vectorValue)) THEN + isNotOK = (obj%argType .NE. Constant) .OR. (obj%returnType .NE. Vector) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%argType '// & + & CHAR_LF//' is NOT Constant '// & + & CHAR_LF//'or UserFunction_::obj%returnType is not Vector.') + RETURN + END IF + tsize = SIZE(vectorValue) + isNotOK = tsize .NE. obj%numReturns + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%numReturns '// & + & CHAR_LF//tostring(obj%numReturns)//'is NOT equal to '// & + & CHAR_LF//' the size of vectorValue ('//tostring(tsize)//').') + RETURN + END IF + CALL Reallocate(obj%vectorValue, SIZE(vectorValue)) + obj%vectorValue = vectorValue + END IF + + IF (PRESENT(matrixValue)) THEN + isNotOK = (obj%argType .NE. Constant) .OR. (obj%returnType .NE. Matrix) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%argType '// & + & CHAR_LF//'is NOT Constant '// & + & CHAR_LF//'or UserFunction_::obj%returnType is not Matrix') + RETURN + END IF + myshape = SHAPE(matrixValue) + + isNotOK = ALL(myshape .NE. obj%returnShape) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%returnType is '// & + & 'Matrix, but shape of matrixValue is not same as obj%returnShape') + RETURN + END IF + + CALL Reallocate(obj%matrixValue, myshape(1), myshape(2)) + obj%matrixValue = matrixValue + END IF + + IF (PRESENT(luaScript)) THEN + obj%isLuaScript = .TRUE. + obj%luaScript = luaScript + IF (PRESENT(luaFunctionName)) THEN + obj%luaFunctionName = luaFunctionName + ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: both luaScript and luaFunctionName '// & + & 'should be present.') + RETURN + END IF + END IF + + IF (PRESENT(scalarFunction)) THEN + isNotOK = obj%returnType .NE. Scalar + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%returnType is not Scalar') + RETURN + END IF + obj%isUserFunctionSet = .TRUE. + obj%scalarFunction => scalarFunction + END IF + + IF (PRESENT(vectorFunction)) THEN + isNotOK = obj%returnType .NE. Vector + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%returnType is not Vector') + RETURN + END IF + obj%isUserFunctionSet = .TRUE. + obj%vectorFunction => vectorFunction + END IF + + IF (PRESENT(matrixFunction)) THEN + isNotOK = obj%returnType .NE. Matrix + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%returnType is not Matrix') + RETURN + END IF + obj%isUserFunctionSet = .TRUE. + obj%matrixFunction => matrixFunction + END IF + +#ifdef DEBUG_VER + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Set()') +#endif +END SUBROUTINE auf_Set1 + END MODULE UserFunction_Class diff --git a/src/modules/Vector/src/Vector_Class.F90 b/src/modules/Vector/src/Vector_Class.F90 index 176575052..3a6d09728 100644 --- a/src/modules/Vector/src/Vector_Class.F90 +++ b/src/modules/Vector/src/Vector_Class.F90 @@ -23,7 +23,13 @@ MODULE Vector_Class USE FPL, ONLY: ParameterList_ IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = "Vector_Class" +CHARACTER(*), PARAMETER :: modName = "Vector_Class" +PUBLIC :: Vector_ +PUBLIC :: VectorPointer_ +PUBLIC :: vec_checkEssentialParam +PUBLIC :: DEALLOCATE +PUBLIC :: RealVector +PUBLIC :: RealVector_Pointer !---------------------------------------------------------------------------- ! Vector_ @@ -44,7 +50,7 @@ MODULE Vector_Class PROCEDURE, PASS(obj) :: checkEssentialParam => vec_checkEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: initiate => vec_initiate PROCEDURE, PUBLIC, PASS(obj) :: Display => vec_Display - PROCEDURE, PUBLIC, PASS(obj) :: Deallocate => vec_Deallocate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => vec_Deallocate FINAL :: vec_Final PROCEDURE, PASS(obj) :: set1 => vec_set1 PROCEDURE, PASS(obj) :: set2 => vec_set2 @@ -62,7 +68,6 @@ MODULE Vector_Class END TYPE Vector_ -PUBLIC :: Vector_ TYPE(Vector_), PARAMETER, PUBLIC :: TypeVector = Vector_() !---------------------------------------------------------------------------- @@ -73,7 +78,6 @@ MODULE Vector_Class CLASS(Vector_), POINTER :: ptr => NULL() END TYPE VectorPointer_ -PUBLIC :: VectorPointer_ !---------------------------------------------------------------------------- ! checkEssentialParam@Constructor @@ -90,7 +94,6 @@ MODULE SUBROUTINE vec_checkEssentialParam(obj, param) END SUBROUTINE vec_checkEssentialParam END INTERFACE -PUBLIC :: vec_checkEssentialParam !---------------------------------------------------------------------------- ! Initiate@Constructor @@ -132,17 +135,12 @@ END SUBROUTINE vec_Initiate ! date: 25 June 2021 ! summary: This routine deallocates the data stored inside the Vector_ obj -INTERFACE +INTERFACE DEALLOCATE MODULE SUBROUTINE vec_Deallocate(obj) CLASS(Vector_), INTENT(INOUT) :: obj END SUBROUTINE vec_Deallocate -END INTERFACE +END INTERFACE DEALLOCATE -INTERFACE Deallocate - MODULE PROCEDURE vec_Deallocate -END INTERFACE Deallocate - -PUBLIC :: Deallocate !---------------------------------------------------------------------------- ! Final@Constructor @@ -162,19 +160,13 @@ END SUBROUTINE vec_Final ! date: 25 June 2021 ! summary: This function returns an instance of [[Vector_]] -INTERFACE +INTERFACE RealVector MODULE FUNCTION vec_Constructor1(param) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param TYPE(Vector_) :: ans END FUNCTION vec_Constructor1 -END INTERFACE - -INTERFACE RealVector - MODULE PROCEDURE vec_Constructor1 END INTERFACE RealVector -PUBLIC :: RealVector - !---------------------------------------------------------------------------- ! Vector_Pointer@Constructor !---------------------------------------------------------------------------- @@ -183,19 +175,13 @@ END FUNCTION vec_Constructor1 ! date: 25 June 2021 ! summary: This function returns an instance of [[Vector_]] -INTERFACE +INTERFACE RealVector_Pointer MODULE FUNCTION vec_Constructor_1(param) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param CLASS(Vector_), POINTER :: ans END FUNCTION vec_Constructor_1 -END INTERFACE - -INTERFACE RealVector_Pointer - MODULE PROCEDURE vec_Constructor_1 END INTERFACE RealVector_Pointer -PUBLIC :: RealVector_Pointer - !---------------------------------------------------------------------------- ! Display@IO !---------------------------------------------------------------------------- @@ -207,7 +193,7 @@ END FUNCTION vec_Constructor_1 INTERFACE MODULE SUBROUTINE vec_Display(obj, msg, unitNo) CLASS(Vector_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: msg + CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo END SUBROUTINE vec_Display END INTERFACE @@ -221,10 +207,10 @@ END SUBROUTINE vec_Display ! summary: This routine sets the single entry of the vector INTERFACE - MODULE SUBROUTINE vec_set1(obj, nodenum, value) + MODULE SUBROUTINE vec_set1(obj, nodenum, VALUE) CLASS(Vector_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: nodenum - REAL(DFP), INTENT(IN) :: value + REAL(DFP), INTENT(IN) :: VALUE END SUBROUTINE vec_set1 END INTERFACE @@ -237,9 +223,9 @@ END SUBROUTINE vec_set1 ! summary: This routine sets all the entries of a vector INTERFACE - MODULE SUBROUTINE vec_set2(obj, value) + MODULE SUBROUTINE vec_set2(obj, VALUE) CLASS(Vector_), INTENT(INOUT) :: obj - REAL(DFP), INTENT(IN) :: value + REAL(DFP), INTENT(IN) :: VALUE END SUBROUTINE vec_set2 END INTERFACE @@ -252,9 +238,9 @@ END SUBROUTINE vec_set2 ! summary: This routine set all the entries by using given vector INTERFACE - MODULE SUBROUTINE vec_set3(obj, value) + MODULE SUBROUTINE vec_set3(obj, VALUE) CLASS(Vector_), INTENT(INOUT) :: obj - REAL(DFP), INTENT(IN) :: value(:) + REAL(DFP), INTENT(IN) :: VALUE(:) END SUBROUTINE vec_set3 END INTERFACE @@ -267,10 +253,10 @@ END SUBROUTINE vec_set3 ! summary: This routine sets the selected entries INTERFACE - MODULE SUBROUTINE vec_set4(obj, nodenum, value) + MODULE SUBROUTINE vec_set4(obj, nodenum, VALUE) CLASS(Vector_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: nodenum(:) - REAL(DFP), INTENT(IN) :: value(:) + REAL(DFP), INTENT(IN) :: VALUE(:) END SUBROUTINE vec_set4 END INTERFACE @@ -283,10 +269,10 @@ END SUBROUTINE vec_set4 ! summary: This routine sets the selected entries INTERFACE - MODULE SUBROUTINE vec_set5(obj, iStart, iEnd, stride, value) + MODULE SUBROUTINE vec_set5(obj, iStart, iEnd, stride, VALUE) CLASS(Vector_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart, iend, stride - REAL(DFP), INTENT(IN) :: value + REAL(DFP), INTENT(IN) :: VALUE END SUBROUTINE vec_set5 END INTERFACE @@ -299,12 +285,12 @@ END SUBROUTINE vec_set5 ! summary: set the vector values using triplet INTERFACE - MODULE SUBROUTINE vec_set6(obj, istart, iend, stride, value) + MODULE SUBROUTINE vec_set6(obj, istart, iend, stride, VALUE) CLASS(Vector_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - REAL(DFP), INTENT(IN) :: value(:) + REAL(DFP), INTENT(IN) :: VALUE(:) END SUBROUTINE vec_set6 END INTERFACE @@ -317,10 +303,10 @@ END SUBROUTINE vec_set6 ! summary: set the selected values of vector INTERFACE - MODULE SUBROUTINE vec_set7(obj, nodeNum, value, storageFMT, dofs) + MODULE SUBROUTINE vec_set7(obj, nodeNum, VALUE, storageFMT, dofs) CLASS(Vector_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: nodeNum(:) - REAL(DFP), INTENT(IN) :: value(:) + REAL(DFP), INTENT(IN) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: storageFMT INTEGER(I4B), OPTIONAL, INTENT(IN) :: dofs(:) END SUBROUTINE vec_set7 @@ -351,7 +337,7 @@ END FUNCTION vec_get1 ! summary: Returns all the entries of the vector INTERFACE - MODULE MODULE FUNCTION vec_get2(obj) RESULT(ans) + MODULE FUNCTION vec_get2(obj) RESULT(ans) CLASS(Vector_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE :: ans(:) END FUNCTION vec_get2 diff --git a/src/modules/VectorField/src/VectorField_Class.F90 b/src/modules/VectorField/src/VectorField_Class.F90 index f4f1a722e..b1ac732ee 100644 --- a/src/modules/VectorField/src/VectorField_Class.F90 +++ b/src/modules/VectorField/src/VectorField_Class.F90 @@ -29,6 +29,7 @@ MODULE VectorField_Class USE HDF5File_Class USE Domain_Class USE DirichletBC_Class +USE FiniteElement_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "VectorField_Class" @@ -63,68 +64,68 @@ MODULE VectorField_Class PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => vField_Initiate1 PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => vField_Initiate2 PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => vField_Deallocate - PROCEDURE, PUBLIC, PASS(obj) :: getPointerOfComponent => & - & vField_getPointerOfComponent + PROCEDURE, PUBLIC, PASS(obj) :: GetPointerOfComponent => & + & vField_GetPointerOfComponent PROCEDURE, PUBLIC, PASS(obj) :: Display => vField_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => vField_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => vField_Export FINAL :: vField_Final !! SetMethods - PROCEDURE, PASS(obj) :: Set1 => vField_set1 - !! Set single entry - PROCEDURE, PASS(obj) :: Set2 => vField_set2 - !! Set all values to a Vector values - PROCEDURE, PASS(obj) :: Set3 => vField_set3 - !! Set all values to a given vector - PROCEDURE, PASS(obj) :: Set4 => vField_set4 - !! Set selected values to given Vector - PROCEDURE, PASS(obj) :: Set5 => vField_set5 - !! Set selected values to given vector - PROCEDURE, PASS(obj) :: Set6 => vField_set6 - !! Set values to a Vector by using triplet - PROCEDURE, PASS(obj) :: Set7 => vField_set7 - !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set8 => vField_set8 - !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set9 => vField_set9 - !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set10 => vField_set10 - !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set11 => vField_set11 - !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set12 => vField_set12 - !! Set values to a vector by using triplet - PROCEDURE, PASS(obj) :: Set13 => vField_set13 - PROCEDURE, PASS(obj) :: Set14 => vField_set14 - PROCEDURE, PASS(obj) :: Set15 => vField_set15 - !! Set selected values using FEVariable + PROCEDURE, PASS(obj) :: Set1 => vField_Set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => vField_Set2 + !! Set all values to a Vector values + PROCEDURE, PASS(obj) :: Set3 => vField_Set3 + !! Set all values to a given vector + PROCEDURE, PASS(obj) :: Set4 => vField_Set4 + !! Set selected values to given Vector + PROCEDURE, PASS(obj) :: Set5 => vField_Set5 + !! Set selected values to given vector + PROCEDURE, PASS(obj) :: Set6 => vField_Set6 + !! Set values to a Vector by using triplet + PROCEDURE, PASS(obj) :: Set7 => vField_Set7 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set8 => vField_Set8 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set9 => vField_Set9 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set10 => vField_Set10 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set11 => vField_Set11 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set12 => vField_Set12 + !! Set values to a vector by using triplet + PROCEDURE, PASS(obj) :: Set13 => vField_Set13 + PROCEDURE, PASS(obj) :: Set14 => vField_Set14 + PROCEDURE, PASS(obj) :: Set15 => vField_Set15 + !! Set selected values using FEVariable GENERIC, PUBLIC :: Set => & - & Set1, set2, set3, set4, set5, set6, & - & Set7, set8, set9, set10, set11, set12, & - & Set13, set14, set15 - - PROCEDURE, PASS(obj) :: get1 => vField_get1 - !! returns the single entry - PROCEDURE, PASS(obj) :: get2 => vField_get2 - !! returns all entries in rank2 array of real - PROCEDURE, PASS(obj) :: get3 => vField_get3 - !! returns selected values in XiJ format - PROCEDURE, PASS(obj) :: get4 => vField_get4 - PROCEDURE, PASS(obj) :: get5 => vField_get5 - PROCEDURE, PASS(obj) :: get6 => vField_get6 - PROCEDURE, PASS(obj) :: get7 => vField_get7 - PROCEDURE, PASS(obj) :: get8 => vField_get8 - PROCEDURE, PASS(obj) :: get9 => vField_get9 - PROCEDURE, PASS(obj) :: get10 => vField_get10 - PROCEDURE, PASS(obj) :: get11 => vField_get11 - GENERIC, PUBLIC :: get => get1, get2, get3, get4, & - & get5, get6, get7, get8, get9, get10, get11 - !! get the entries of Vector field - PROCEDURE, PASS(obj) :: vField_applyDirichletBC1 - PROCEDURE, PASS(obj) :: vField_applyDirichletBC2 - GENERIC, PUBLIC :: applyDirichletBC => & - & vField_applyDirichletBC1, & - & vField_applyDirichletBC2 + & Set1, Set2, Set3, Set4, Set5, Set6, & + & Set7, Set8, Set9, Set10, Set11, Set12, & + & Set13, Set14, Set15 + + PROCEDURE, PASS(obj) :: Get1 => vField_Get1 + !! returns the single entry + PROCEDURE, PASS(obj) :: Get2 => vField_Get2 + !! returns all entries in rank2 array of real + PROCEDURE, PASS(obj) :: Get3 => vField_Get3 + !! returns selected values in XiJ format + PROCEDURE, PASS(obj) :: Get4 => vField_Get4 + PROCEDURE, PASS(obj) :: Get5 => vField_Get5 + PROCEDURE, PASS(obj) :: Get6 => vField_Get6 + PROCEDURE, PASS(obj) :: Get7 => vField_Get7 + PROCEDURE, PASS(obj) :: Get8 => vField_Get8 + PROCEDURE, PASS(obj) :: Get9 => vField_Get9 + PROCEDURE, PASS(obj) :: Get10 => vField_Get10 + PROCEDURE, PASS(obj) :: Get11 => vField_Get11 + GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, & + & Get5, Get6, Get7, Get8, Get9, Get10, Get11 + !! Get the entries of Vector field + PROCEDURE, PASS(obj) :: vField_ApplyDirichletBC1 + PROCEDURE, PASS(obj) :: vField_ApplyDirichletBC2 + GENERIC, PUBLIC :: ApplyDirichletBC => & + & vField_ApplyDirichletBC1, & + & vField_ApplyDirichletBC2 END TYPE VectorField_ TYPE(VectorField_), PARAMETER, PUBLIC :: TypeVectorField = & @@ -148,12 +149,15 @@ MODULE VectorField_Class ! INTERFACE MODULE SUBROUTINE SetVectorFieldParam(param, name, engine, & - & spaceCompo, fieldType) + & spaceCompo, fieldType, comm, local_n, global_n) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: name CHARACTER(*), INTENT(IN) :: engine INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), OPTIONAL, INTENT(IN) :: fieldType + INTEGER(I4B), OPTIONAL, INTENT(IN) :: comm + INTEGER(I4B), OPTIONAL, INTENT(IN) :: local_n + INTEGER(I4B), OPTIONAL, INTENT(IN) :: global_n END SUBROUTINE SetVectorFieldParam END INTERFACE @@ -204,6 +208,31 @@ MODULE SUBROUTINE vField_Initiate1(obj, param, dom) END SUBROUTINE vField_Initiate1 END INTERFACE VectorFieldInitiate1 +!---------------------------------------------------------------------------- +! Initiate@Constructor +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 25 June 2021 +! summary: This subroutine initiates the VectorField_ object +! +!# Introduction +! This routine initiate the vector field object. +! `param` contains the information of parameters required to initiate the +! vector. There are essential and optional information. +! Essential information are described below. +! - `name` character defining the name of vector field +! - `spaceCompo` is the total degree of freedom or components +! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL + +INTERFACE + MODULE SUBROUTINE vField_Initiate1_old(obj, param, dom) + CLASS(VectorField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE vField_Initiate1_old +END INTERFACE + !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -447,7 +476,7 @@ END SUBROUTINE vField_Set3 !### Usage ! !```fortran -! call reallocate( real2, 3, dom%getTotalNodes() ) +! call reallocate( real2, 3, dom%GetTotalNodes() ) ! real2 = 1.0_DFP ! call obj%Set( value=real2 ) ! call obj%display( "test-4: vector field = " ) @@ -480,7 +509,7 @@ END SUBROUTINE vField_Set4 !### Usage ! !```fortran -! call reallocate( real1, dom%getTotalNodes() ) +! call reallocate( real1, dom%GetTotalNodes() ) ! real1 = 3.0_DFP ! call obj%Set( value=real1, spaceCompo=3 ) ! call obj%display( "test-5: vector field = " ) @@ -790,12 +819,12 @@ END SUBROUTINE vField_Set15 ! In this case this routine returns the entire vector of spacecompo. INTERFACE - MODULE SUBROUTINE vField_get1(obj, VALUE, globalNode, spaceCompo) + MODULE SUBROUTINE vField_Get1(obj, VALUE, globalNode, spaceCompo) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode INTEGER(I4B), OPTIONAL, INTENT(IN) :: spaceCompo - END SUBROUTINE vField_get1 + END SUBROUTINE vField_Get1 END INTERFACE !---------------------------------------------------------------------------- @@ -804,14 +833,14 @@ END SUBROUTINE vField_get1 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine get all the entries by using given Vector field +! summary: This routine Get all the entries by using given Vector field INTERFACE - MODULE SUBROUTINE vField_get2(obj, VALUE, force3D) + MODULE SUBROUTINE vField_Get2(obj, VALUE, force3D) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) LOGICAL(LGT), OPTIONAL, INTENT(IN) :: force3D - END SUBROUTINE vField_get2 + END SUBROUTINE vField_Get2 END INTERFACE !---------------------------------------------------------------------------- @@ -823,12 +852,12 @@ END SUBROUTINE vField_get2 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE vField_get3(obj, VALUE, globalNode, force3D) + MODULE SUBROUTINE vField_Get3(obj, VALUE, globalNode, force3D) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: globalNode(:) LOGICAL(LGT), OPTIONAL, INTENT(IN) :: force3D - END SUBROUTINE vField_get3 + END SUBROUTINE vField_Get3 END INTERFACE !---------------------------------------------------------------------------- @@ -840,12 +869,12 @@ END SUBROUTINE vField_get3 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE vField_get4(obj, VALUE, globalNode, spaceCompo) + MODULE SUBROUTINE vField_Get4(obj, VALUE, globalNode, spaceCompo) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: spaceCompo - END SUBROUTINE vField_get4 + END SUBROUTINE vField_Get4 END INTERFACE !---------------------------------------------------------------------------- @@ -857,12 +886,12 @@ END SUBROUTINE vField_get4 ! summary: This routine returns the selected entries INTERFACE - MODULE SUBROUTINE vField_get5(obj, VALUE, globalNode, spaceCompo) + MODULE SUBROUTINE vField_Get5(obj, VALUE, globalNode, spaceCompo) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode INTEGER(I4B), INTENT(IN) :: spaceCompo - END SUBROUTINE vField_get5 + END SUBROUTINE vField_Get5 END INTERFACE !---------------------------------------------------------------------------- @@ -874,13 +903,13 @@ END SUBROUTINE vField_get5 ! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE vField_get6(obj, VALUE, istart, iend, stride) + MODULE SUBROUTINE vField_Get6(obj, VALUE, istart, iend, stride) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:, :) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride - END SUBROUTINE vField_get6 + END SUBROUTINE vField_Get6 END INTERFACE !---------------------------------------------------------------------------- @@ -892,14 +921,14 @@ END SUBROUTINE vField_get6 ! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE vField_get7(obj, VALUE, istart, iend, stride, spaceCompo) + MODULE SUBROUTINE vField_Get7(obj, VALUE, istart, iend, stride, spaceCompo) CLASS(VectorField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: istart INTEGER(I4B), INTENT(IN) :: iend INTEGER(I4B), INTENT(IN) :: stride INTEGER(I4B), INTENT(IN) :: spaceCompo - END SUBROUTINE vField_get7 + END SUBROUTINE vField_Get7 END INTERFACE !---------------------------------------------------------------------------- @@ -911,11 +940,11 @@ END SUBROUTINE vField_get7 ! summary: This routine returns the selected entries in FEVariable INTERFACE - MODULE SUBROUTINE vField_get8(obj, VALUE, globalNode) + MODULE SUBROUTINE vField_Get8(obj, VALUE, globalNode) CLASS(VectorField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode(:) - END SUBROUTINE vField_get8 + END SUBROUTINE vField_Get8 END INTERFACE !---------------------------------------------------------------------------- @@ -927,11 +956,11 @@ END SUBROUTINE vField_get8 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE vField_get9(obj, VALUE, spaceCompo) + MODULE SUBROUTINE vField_Get9(obj, VALUE, spaceCompo) CLASS(VectorField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: spaceCompo - END SUBROUTINE vField_get9 + END SUBROUTINE vField_Get9 END INTERFACE !---------------------------------------------------------------------------- @@ -943,14 +972,14 @@ END SUBROUTINE vField_get9 ! summary: This routine return value in FEVariable INTERFACE - MODULE SUBROUTINE vField_get10(obj, VALUE) + MODULE SUBROUTINE vField_Get10(obj, VALUE) CLASS(VectorField_), INTENT(IN) :: obj CLASS(VectorField_), INTENT(INOUT) :: VALUE - END SUBROUTINE vField_get10 + END SUBROUTINE vField_Get10 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -958,18 +987,18 @@ END SUBROUTINE vField_get10 ! summary: Get value INTERFACE -MODULE SUBROUTINE vField_get11(obj, ivar, idof, VALUE, ivar_value, idof_value) +MODULE SUBROUTINE vField_Get11(obj, ivar, idof, VALUE, ivar_value, idof_value) CLASS(VectorField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof INTEGER(I4B), INTENT(IN) :: ivar_value INTEGER(I4B), INTENT(IN) :: idof_value - END SUBROUTINE vField_get11 + END SUBROUTINE vField_Get11 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -977,14 +1006,14 @@ END SUBROUTINE vField_get11 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE vField_applyDirichletBC1(obj, dbc) + MODULE SUBROUTINE vField_ApplyDirichletBC1(obj, dbc) CLASS(VectorField_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc - END SUBROUTINE vField_applyDirichletBC1 + END SUBROUTINE vField_ApplyDirichletBC1 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -992,14 +1021,14 @@ END SUBROUTINE vField_applyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE vField_applyDirichletBC2(obj, dbc) + MODULE SUBROUTINE vField_ApplyDirichletBC2(obj, dbc) CLASS(VectorField_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) - END SUBROUTINE vField_applyDirichletBC2 + END SUBROUTINE vField_ApplyDirichletBC2 END INTERFACE !---------------------------------------------------------------------------- -! getPointerOfComponent@GetMethods +! GetPointerOfComponent@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -1007,11 +1036,11 @@ END SUBROUTINE vField_applyDirichletBC2 ! summary: This routine returns pointer to a specific component INTERFACE - MODULE FUNCTION vField_getPointerOfComponent(obj, spaceCompo) RESULT(ans) + MODULE FUNCTION vField_GetPointerOfComponent(obj, spaceCompo) RESULT(ans) CLASS(VectorField_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: spaceCompo REAL(DFP), POINTER :: ans(:) - END FUNCTION vField_getPointerOfComponent + END FUNCTION vField_GetPointerOfComponent END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/modules/easifemClasses/src/easifemClasses.F90 b/src/modules/easifemClasses/src/easifemClasses.F90 index 613f434b9..0f3b40bbd 100644 --- a/src/modules/easifemClasses/src/easifemClasses.F90 +++ b/src/modules/easifemClasses/src/easifemClasses.F90 @@ -16,9 +16,8 @@ ! MODULE easifemClasses -#ifdef USE_GMSH_SDK USE Gmsh_Class -#endif +USE GmshStructuredMesh_Class USE CommandLine_Method USE ExceptionHandler_Class @@ -55,10 +54,7 @@ MODULE easifemClasses USE LinSolver_Class USE LinSolverFactory -USE AbstractBC_Class -USE DirichletBC_Class -USE NeumannBC_Class -USE NitscheBC_Class +USE BoundaryCondition USE PolynomialFactory USE UserFunction_Class @@ -70,4 +66,6 @@ MODULE easifemClasses USE Plot_Method ! USE ogpf + +USE TomlUtility END MODULE easifemClasses diff --git a/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@GetMethods.F90 b/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@GetMethods.F90 index 0fe49c4e4..662b89378 100644 --- a/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@GetMethods.F90 +++ b/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@GetMethods.F90 @@ -20,6 +20,152 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! solverName_ToInteger +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solverName_ToInteger +ans = obj%GetLinSolverCodeFromName(name) +END PROCEDURE solverName_ToInteger + +!---------------------------------------------------------------------------- +! preconditionOption_ToInteger +!---------------------------------------------------------------------------- + +MODULE PROCEDURE preconditionOption_ToInteger +TYPE(String) :: astr +astr = UpperCase(name) +ans = NO_PRECONDITION +SELECT CASE (astr%chars()) +CASE ("NO", "NONE", "NO_PRECONDITION") + ans = NO_PRECONDITION +CASE ("LEFT", "LEFT_PRECONDITION") + ans = LEFT_PRECONDITION +CASE ("RIGHT", "RIGHT_PRECONDITION") + ans = RIGHT_PRECONDITION +CASE ("LEFTRIGHT", "RIGHTLEFT", "LEFTRIGHT_PRECONDITION", & + & "RIGHTLEFT_PRECONDITION") + ans = LEFT_RIGHT_PRECONDITION +END SELECT +END PROCEDURE preconditionOption_ToInteger + +!---------------------------------------------------------------------------- +! convergenceIn_ToInteger +!---------------------------------------------------------------------------- + +MODULE PROCEDURE convergenceIn_ToInteger +TYPE(String) :: astr +astr = UpperCase(name) +ans = ConvergenceInRes +SELECT CASE (astr%chars()) +CASE ("RESIDUAL") + ans = ConvergenceInRes +CASE ("SOL") + ans = ConvergenceInSol +CASE ("RESIDUALSOL", "SOLRESIDUAL") + ans = ConvergenceInResSol +END SELECT +END PROCEDURE convergenceIn_ToInteger + +!---------------------------------------------------------------------------- +! convergenceType_ToInteger +!---------------------------------------------------------------------------- + +MODULE PROCEDURE convergenceType_ToInteger +TYPE(String) :: astr +astr = UpperCase(name) +SELECT CASE (astr%chars()) +CASE ("RELATIVE") + ans = RelativeConvergence +CASE ("ABSOLUTE") + ans = AbsoluteConvergence +END SELECT +END PROCEDURE convergenceType_ToInteger + +!---------------------------------------------------------------------------- +! scale_ToInteger +!---------------------------------------------------------------------------- + +MODULE PROCEDURE scale_ToInteger +TYPE(String) :: astr +astr = UpperCase(name) +SELECT CASE (astr%chars()) +CASE ("NO", "NONE") + ans = scale_none +CASE ("JACOBI") + ans = scale_jacobi +CASE ("SYMDIAG") + ans = scale_symm_diag +END SELECT +END PROCEDURE scale_ToInteger + +!---------------------------------------------------------------------------- +! preconditionName_ToInteger +!---------------------------------------------------------------------------- + +MODULE PROCEDURE preconditionName_ToInteger +TYPE(String) :: astr +astr = UpperCase(name) + +SELECT CASE (astr%chars()) +CASE ("NONE") + ans = PRECOND_NONE + +CASE ("JACOBI") + ans = PRECOND_JACOBI + +CASE ("ILU") + ans = PRECOND_ILU + +CASE ("SSOR") + ans = PRECOND_SSOR + +CASE ("HYBRID") + ans = PRECOND_HYBRID + +CASE ("IS") + ans = PRECOND_IS + +CASE ("SAINV") + ans = PRECOND_SAINV + +CASE ("SAAMG") + ans = PRECOND_SAAMG + +CASE ("ILUC") + ans = PRECOND_ILUC + +CASE ("ADDS") + ans = PRECOND_ADDS + +CASE ("ILUTP") + ans = PRECOND_ILUTP + +CASE ("ILUD") + ans = PRECOND_ILUD + +CASE ("ILUDP") + ans = PRECOND_ILUDP + +CASE ("ILU0") + ans = PRECOND_ILU0 + +CASE ("ILUK") + ans = PRECOND_ILUK + +CASE ("ILUT") + ans = PRECOND_ILUT +END SELECT +END PROCEDURE preconditionName_ToInteger + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE als_GetPrefix +ans = myprefix +END PROCEDURE als_GetPrefix + !---------------------------------------------------------------------------- ! GetParam !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@IOMethods.F90 b/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@IOMethods.F90 index 74f4a9dd1..e865c367b 100644 --- a/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@IOMethods.F90 +++ b/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@IOMethods.F90 @@ -17,35 +17,400 @@ SUBMODULE(AbstractLinSolver_Class) IOMethods USE BaseMethod +USE tomlf, ONLY: & + & toml_error, & + & toml_load, & + & toml_parser_config, & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_context, & + & toml_terminal, & + & toml_load, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! ImportParamFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE als_ImportParamFromToml +CHARACTER(*), PARAMETER :: myName = "als_ImportParamFromToml()" +INTEGER(I4B) :: origin, stat +TYPE(toml_table), POINTER :: child, node + +TYPE(String) :: engine, solverName, preconditionOption, & + & p_name, convergenceIn, convergenceType, scale, & + & p_hybrid_i + +INTEGER(I4B) :: maxIter, krylovSubspaceSize, bicgstab_ell, & + & p_ilu_lfil, p_ilu_mbloc, p_ilu_fill, p_hybrid_maxiter, & + & p_hybrid_ell, p_hybrid_restart, p_is_m, p_adds_iter + +REAL(DFP) :: atol, rtol, sor_omega, p_is_alpha, & + & p_ilu_droptol, p_ilu_permtol, p_ilu_alpha, p_ssor_omega, & + & p_hybrid_tol, p_hybrid_omega, p_sainv_drop, p_saamg_theta, & + & p_iluc_drop, p_iluc_rate + +LOGICAL(LGT) :: relativeToRHS, initx_zeros, p_saamg_unsym, & + & p_adds + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportParamFromToml()') +#endif + +CALL toml_get(table, "engine", engine%raw, & + & default_engine, origin=origin, stat=stat) + +CALL toml_get(table, "solverName", solverName%raw, & + & default_solverName_char, origin=origin, stat=stat) + +CALL toml_get(table, "convergenceIn", convergenceIn%raw, & + & default_convergenceIn_char, origin=origin, stat=stat) + +CALL toml_get(table, "convergenceType", convergenceType%raw, & + & default_convergenceType_char, origin=origin, stat=stat) + +CALL toml_get(table, "scale", scale%raw, & + & default_scale_char, origin=origin, stat=stat) + +CALL toml_get(table, "maxIter", maxIter, & + & default_maxIter, origin=origin, stat=stat) + +CALL toml_get(table, "krylovSubspaceSize", krylovSubspaceSize, & + & default_krylovSubspaceSize, origin=origin, stat=stat) + +CALL toml_get(table, "bicgstab_ell", bicgstab_ell, & + & default_bicgstab_ell, origin=origin, stat=stat) + +CALL toml_get(table, "atol", atol, & + & default_atol, origin=origin, stat=stat) + +CALL toml_get(table, "rtol", rtol, & + & default_rtol, origin=origin, stat=stat) + +CALL toml_get(table, "relativeToRHS", relativeToRHS, & + & default_relativeToRHS, origin=origin, stat=stat) + +CALL toml_get(table, "initx_zeros", initx_zeros, & + & default_initx_zeros, origin=origin, stat=stat) + +CALL toml_get(table, "initx_zeros", initx_zeros, & + & default_initx_zeros, origin=origin, stat=stat) + +CALL toml_get(table, "sor_omega", sor_omega, & + & default_sor_omega, origin=origin, stat=stat) + +node => NULL() +CALL toml_get(table, "precondition", node, origin=origin, & + & stat=stat, requested=.FALSE.) + +preconditionOption = default_preconditionOption_char +p_name = default_p_name_char +p_ilu_lfil = default_ilu_lfil +p_ilu_mbloc = default_ilu_mbloc +p_ilu_fill = default_ilu_fill +p_ilu_droptol = default_ilu_droptol +p_ilu_permtol = default_ilu_permtol +p_ilu_alpha = default_ilu_alpha +p_hybrid_i = default_hybrid_i_char +p_hybrid_maxiter = default_hybrid_maxiter +p_hybrid_ell = default_hybrid_ell +p_hybrid_restart = default_hybrid_restart +p_hybrid_tol = default_hybrid_tol +p_hybrid_omega = default_hybrid_omega +p_is_m = default_is_m +p_is_alpha = default_is_alpha +p_adds_iter = default_adds_iter +p_adds = default_adds +p_ssor_omega = default_ssor_omega +p_sainv_drop = default_sainv_drop +p_saamg_theta = default_saamg_theta +p_saamg_unsym = default_saamg_unsym +p_iluc_drop = default_iluc_drop +p_iluc_rate = default_iluc_rate + +IF (ASSOCIATED(node)) THEN + CALL toml_get(node, "option", preconditionOption%raw, origin=origin, & + & stat=stat) + CALL toml_get(node, "name", p_name%raw, origin=origin, stat=stat) + + child => NULL() + CALL toml_get(node, "ilu", child, origin=origin, stat=stat, & + & requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "lfil", p_ilu_lfil, origin=origin, stat=stat) + + CALL toml_get(child, "mbloc", p_ilu_mbloc, origin=origin, stat=stat) + + CALL toml_get(child, "fill", p_ilu_fill, origin=origin, stat=stat) + + CALL toml_get(child, "droptol", p_ilu_droptol, origin=origin, stat=stat) + + CALL toml_get(child, "permtol", p_ilu_permtol, origin=origin, stat=stat) + + CALL toml_get(child, "alpha", p_ilu_alpha, origin=origin, stat=stat) + + END IF + + child => NULL() + CALL toml_get(node, "hybrid", child, origin=origin, stat=stat, & + & requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "name", p_hybrid_i%raw, default_hybrid_i_char, & + & origin=origin, stat=stat) + CALL toml_get(child, "maxIter", p_hybrid_maxiter, & + & default_hybrid_maxiter, origin=origin, stat=stat) + CALL toml_get(child, "ell", p_hybrid_ell, & + & default_hybrid_ell, origin=origin, stat=stat) + CALL toml_get(child, "restart", & + & p_hybrid_restart, & + & default_hybrid_restart, origin=origin, stat=stat) + CALL toml_get(child, "tol", p_hybrid_tol, & + & default_hybrid_tol, origin=origin, stat=stat) + CALL toml_get(child, "omega", & + & p_hybrid_omega, & + & default_hybrid_omega, origin=origin, stat=stat) + END IF + + child => NULL() + CALL toml_get(node, "is", child, origin=origin, stat=stat, & + & requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "m", p_is_m, & + & default_is_m, origin=origin, stat=stat) + CALL toml_get(child, "p_is_alpha", p_is_alpha, & + & default_is_alpha, origin=origin, stat=stat) + END IF + + child => NULL() + CALL toml_get(node, "adds", child, origin=origin, & + & stat=stat, requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "iter", p_adds_iter, origin=origin, stat=stat) + CALL toml_get(child, "isAdditiveSchwarz", p_adds, & + & origin=origin, stat=stat) + END IF + + child => NULL() + CALL toml_get(node, "ssor", child, origin=origin, & + & stat=stat, requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "omega", p_ssor_omega, origin=origin, stat=stat) + END IF + + child => NULL() + CALL toml_get(node, "sainv", child, origin=origin, & + & stat=stat, requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "drop", p_sainv_drop, origin=origin, stat=stat) + END IF + + child => NULL() + CALL toml_get(node, "saamg", child, origin=origin, & + & stat=stat, requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "theta", p_saamg_theta, origin=origin, stat=stat) + CALL toml_get(child, "unsym", p_saamg_unsym, origin=origin, stat=stat) + END IF + + child => NULL() + CALL toml_get(node, "iluc", child, origin=origin, & + & stat=stat, requested=.FALSE.) + IF (ASSOCIATED(child)) THEN + CALL toml_get(child, "drop", p_iluc_drop, origin=origin, stat=stat) + CALL toml_get(child, "rate", p_iluc_rate, origin=origin, stat=stat) + END IF +END IF + +CALL SetAbstractLinSolverParam( & + & param=param, & + & prefix=obj%GetPrefix(), & + & engine=engine%chars(), & + & solverName=obj%solverName_ToInteger(solverName%chars()), & + & preconditionOption= & + & obj%preconditionOption_ToInteger(preconditionOption%chars()), & + & maxIter=maxIter, & + & atol=atol, & + & rtol=rtol, & + & convergenceIn= & + & obj%convergenceIn_ToInteger(convergenceIn%chars()), & + & convergenceType= & + & obj%convergenceType_ToInteger(convergenceType%chars()), & + & relativeToRHS=relativeToRHS, & + & krylovSubspaceSize=krylovSubspaceSize, & + & scale=obj%scale_ToInteger(scale%chars()), & + & initx_zeros=initx_zeros, & + & bicgstab_ell=bicgstab_ell, & + & sor_omega=sor_omega, & + & p_name=obj%preconditionName_ToInteger(p_name%chars()), & + & p_ilu_lfil=p_ilu_lfil, & + & p_ilu_mbloc=p_ilu_mbloc, & + & p_ilu_droptol=p_ilu_droptol, & + & p_ilu_permtol=p_ilu_permtol, & + & p_ilu_alpha=p_ilu_alpha, & + & p_ilu_fill=p_ilu_fill, & + & p_ssor_omega=p_ssor_omega, & + & p_hybrid_i=obj%solverName_ToInteger(p_hybrid_i%chars()), & + & p_hybrid_maxiter=p_hybrid_maxiter, & + & p_hybrid_tol=p_hybrid_tol, & + & p_hybrid_omega=p_hybrid_omega, & + & p_hybrid_ell=p_hybrid_ell, & + & p_hybrid_restart=p_hybrid_restart, & + & p_is_alpha=p_is_alpha, & + & p_is_m=p_is_m, & + & p_sainv_drop=p_sainv_drop, & + & p_saamg_unsym=p_saamg_unsym, & + & p_saamg_theta=p_saamg_theta, & + & p_iluc_drop=p_iluc_drop, & + & p_iluc_rate=p_iluc_rate, & + & p_adds=p_adds, & + & p_adds_iter=p_adds_iter & +& ) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE als_ImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE als_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "als_ImportFromToml()" +TYPE(ParameterList_) :: param +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +CALL param%Initiate() +CALL obj%ImportParamFromToml(param=param, table=table) +CALL obj%Initiate(param) +CALL param%DEALLOCATE() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml()') +#endif +END PROCEDURE als_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE als_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "als_ImportFromToml2()" +LOGICAL(LGT) :: isNotOpen, isNotRead +LOGICAL(LGT), PARAMETER :: color = .TRUE. +INTEGER(I4B), PARAMETER :: detail = 1 +TYPE(toml_error), ALLOCATABLE :: error +TYPE(toml_context) :: context +TYPE(toml_terminal) :: terminal +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +INTEGER(I4B) :: origin, stat + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml2()') +#endif + +terminal = toml_terminal(color) + +IF (PRESENT(afile)) THEN + isNotOpen = .NOT. afile%IsOpen() + isNotRead = .NOT. afile%IsRead() + + IF (isNotRead .OR. isNotOpen) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The file is not open or does not have '// & + & 'the access to read!') + END IF + + CALL toml_load(table, & + & afile%GetUnitNo(), & + & context=context, & + & config=toml_parser_config(color=terminal, context_detail=detail), & + & error=error & + & ) + +ELSEIF (PRESENT(filename)) THEN + CALL toml_load(table, & + & filename, & + & context=context, & + & config=toml_parser_config(color=terminal, context_detail=detail), & + & error=error & + & ) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +IF (ALLOCATED(error)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Some error occured while parsing toml file'// & + & ' with following message: '//error%message) +END IF + +node => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find '//tomlName//" table in config.") +END IF + +CALL obj%ImportFromToml(table=node) + +#ifdef DEBUG_VER +IF (PRESENT(printToml)) THEN + CALL Display(toml_serialize(node), & + & "abstractLinSolver toml config = "//CHAR_LF, & + & unitNo=stdout) +END IF +#endif + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml2()') +#endif +END PROCEDURE als_ImportFromToml2 + !---------------------------------------------------------------------------- ! Display !---------------------------------------------------------------------------- MODULE PROCEDURE als_Display -CALL Display(msg, "#", unitNo=unitno) -CALL Display("# engine : "//obj%engine%chars(), unitNo=unitno) -CALL Display(obj%isInitiated, "# isInitiated : ", unitNo=unitno) -CALL Display(obj%solverName, "# solverName : ", unitNo=unitno) -CALL Display(obj%preconditionOption, "# preconditionOption : ", unitNo=unitno) -CALL Display(obj%convergenceIn, "# convergenceIn : ", unitNo=unitno) -CALL Display(obj%convergenceType, "# convergenceType : ", unitNo=unitno) -CALL Display(obj%maxIter, "# maxIter : ", unitNo=unitno) -CALL Display(obj%relativeToRHS, "# relativeToRHS : ", unitNo=unitno) -CALL Display(obj%KrylovSubspaceSize, "# KrylovSubspaceSize : ", unitNo=unitno) -CALL Display(obj%atol, "# atol : ", unitNo=unitno) -CALL Display(obj%rtol, "# rtol : ", unitNo=unitno) -CALL Display(obj%ierr, "# ierr : ", unitNo=unitno) -CALL Display(obj%iter, "# iter : ", unitNo=unitno) +CALL Display(msg, unitNo=unitno) +CALL Display("engine : "//obj%engine%chars(), unitNo=unitno) +CALL Display(obj%isInitiated, "isInitiated : ", unitNo=unitno) +CALL Display(obj%solverName, "solverName : ", unitNo=unitno) +CALL Display(obj%preconditionOption, "preconditionOption : ", unitNo=unitno) +CALL Display(obj%convergenceIn, "convergenceIn : ", unitNo=unitno) +CALL Display(obj%convergenceType, "convergenceType : ", unitNo=unitno) +CALL Display(obj%maxIter, "maxIter : ", unitNo=unitno) +CALL Display(obj%relativeToRHS, "relativeToRHS : ", unitNo=unitno) +CALL Display(obj%KrylovSubspaceSize, "KrylovSubspaceSize : ", unitNo=unitno) +CALL Display(obj%atol, "atol : ", unitNo=unitno) +CALL Display(obj%rtol, "rtol : ", unitNo=unitno) +CALL Display(obj%ierr, "ierr : ", unitNo=unitno) +CALL Display(obj%iter, "iter : ", unitNo=unitno) IF (ASSOCIATED(obj%Amat)) THEN CALL Display("Amat is ASSOCIATED", unitNo=unitno) ELSE CALL Display("Amat is NOT ASSOCIATED", unitNo=unitno) END IF IF (ALLOCATED(obj%RES)) & - & CALL Display("# obj%RES is ALLOCATED", unitNo=unitno) + & CALL Display("obj%RES is ALLOCATED", unitNo=unitno) END PROCEDURE als_Display !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@SetMethods.F90 b/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@SetMethods.F90 index 5afe62e35..a4fb8c1ee 100644 --- a/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@SetMethods.F90 +++ b/src/submodules/AbstractLinSolver/src/AbstractLinSolver_Class@SetMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(AbstractLinSolver_Class) SetMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS @@ -63,267 +64,377 @@ ! setAbstractLinSolverParam !---------------------------------------------------------------------------- -MODULE PROCEDURE setAbstractLinSolverParam -INTEGER(I4B) :: ierr -! +MODULE PROCEDURE SetAbstractLinSolverParam +CHARACTER(*), PARAMETER :: myName = "SetLinSolverParam()" +INTEGER(I4B) :: p_name0 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] SetAbstractLinSolverParam()') +#endif + +IF (.NOT. PRESENT(solverName)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: solverName should be present') +END IF + +IF (solverName .EQ. LIS_SOR) THEN + IF (.NOT. PRESENT(sor_omega)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: For solverName LIS_SOR sor_omega should be present') + END IF +END IF + +IF (solverName .EQ. LIS_BICGSTABL) THEN + IF (.NOT. PRESENT(bicgstab_ell)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: For solverName LIS_BICGSTABL bicgstab_ell '// & + & 'should be present') + END IF +END IF + +IF (.NOT. PRESENT(preconditionOption)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: preconditionOption should be present') +END IF + +p_name0 = INPUT(option=p_name, default=PRECOND_NONE) + +IF (preconditionOption .NE. PRECOND_NONE) THEN + IF (.NOT. PRESENT(p_name)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: preconditionOption is active, therefore, '// & + & 'precondition name (p_name) should be present') + END IF +END IF + +SELECT CASE (p_name0) +CASE (PRECOND_NONE) + !! Do nothing +CASE (PRECOND_ILUT) + IF (.NOT. PRESENT(p_ilu_droptol) .OR. & + & .NOT. PRESENT(p_ilu_lfil)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILUT (sparsekit) '// & + & 'p_ilu_droptol and p_ilu_lfil should be present!') + END IF +CASE (PRECOND_ILUTP) + IF (.NOT. PRESENT(p_ilu_droptol) .OR. & + & .NOT. PRESENT(p_ilu_lfil) .OR. & + & .NOT. PRESENT(p_ilu_permtol) .OR. & + & .NOT. PRESENT(p_ilu_mbloc)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILUTP (sparsekit) '// & + & 'p_ilu_droptol, p_ilu_lfil, p_ilu_permtol, '// & + & 'p_ilu_mbloc should be present!') + END IF +CASE (PRECOND_ILUD) + IF (.NOT. PRESENT(p_ilu_droptol) .OR. & + & .NOT. PRESENT(p_ilu_alpha)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILUTP (sparsekit) '// & + & 'p_ilu_droptol and p_ilu_alpha should be present!') + END IF +CASE (PRECOND_ILUDP) + IF (.NOT. PRESENT(p_ilu_droptol) .OR. & + & .NOT. PRESENT(p_ilu_alpha) .OR. & + & .NOT. PRESENT(p_ilu_permtol) .OR. & + & .NOT. PRESENT(p_ilu_mbloc)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILUDP (sparsekit) p_ilu_droptol, '// & + & 'p_ilu_alpha, p_ilu_permtol, '// & + & 'p_ilu_mbloc should be present!!!') + END IF +CASE (PRECOND_ILUK) + IF (.NOT. PRESENT(p_ilu_lfil)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILUK (sparsekit) p_ilu_lfil '// & + & 'should be present!') + END IF + +! LIS LIB +CASE (PRECOND_ILU) + IF (.NOT. PRESENT(p_ilu_fill)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILU (LIS) p_ilu_fill should be present!') + END IF +CASE (PRECOND_SSOR) + IF (.NOT. PRESENT(p_ssor_omega)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_SSOR (LIS) p_ssor_omega '// & + & 'should be present!') + END IF +CASE (PRECOND_HYBRID) + + IF (.NOT. PRESENT(p_hybrid_i) .OR. & + & .NOT. PRESENT(p_hybrid_tol) .OR. & + & .NOT. PRESENT(p_hybrid_maxiter) & + & ) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_HYBRID (LIS) p_hybrid_i '// & + & 'p_hybrid_maxiter p_hybrid_tol '// & + & ' should be present!!!') + END IF + + IF (p_hybrid_i .EQ. LIS_SOR) THEN + IF (.NOT. PRESENT(p_hybrid_omega)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_HYBRID (LIS) and '// & + & 'p_hybrid_i=LIS_SOR, p_hybrid_omega '// & + & ' should be present!!!') + END IF + END IF + + IF (p_hybrid_i .EQ. LIS_BICGSTABL) THEN + IF (.NOT. PRESENT(p_hybrid_ell)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_HYBRID (LIS) and '// & + & 'p_hybrid_i=LIS_BICGSTABL, '// & + & ' p_hybrid_ell should be present!!!') + END IF + END IF + + IF (ANY(p_hybrid_i .EQ. [LIS_GMRES, LIS_ORTHOMIN, LIS_FGMRES])) THEN + IF (.NOT. PRESENT(p_hybrid_restart)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_HYBRID (LIS), '// & + & 'and p_hybrid_i=LIS_GMRES LIS_ORTHOMIN LIS_FGMRES, '// & + & 'p_hybrid_restart should be present!!!') + END IF + END IF + +CASE (PRECOND_IS) + IF (.NOT. PRESENT(p_is_alpha) .OR. & + & .NOT. PRESENT(p_is_m)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_IS (LIS) p_is_alpha, '// & + & 'p_is_m should be present!') + END IF + +CASE (PRECOND_SAINV) + IF (.NOT. PRESENT(p_sainv_drop)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_SAINV (LIS) '// & + & 'p_sainv_drop should be present!') + END IF + +CASE (PRECOND_SAAMG) + + IF ( & + & .NOT. PRESENT(p_saamg_theta) .OR. & + & .NOT. PRESENT(p_saamg_unsym)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_SAAMG (LIS) '// & + & 'p_saamg_theta, p_saamg_unsym '// & + & 'should be present!!!') + END IF + +CASE (PRECOND_ILUC) + + IF ( & + & .NOT. PRESENT(p_iluc_drop) .OR. & + & .NOT. PRESENT(p_iluc_rate)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ILUC (LIS) p_iluc_drop, p_iluc_rate'// & + & 'should be present!!!') + END IF + +CASE (PRECOND_ADDS) + + IF ( & + & .NOT. PRESENT(p_adds) .OR. & + & .NOT. PRESENT(p_adds_iter)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: for PRECOND_ADDS (LIS) p_adds, p_adds_iter'// & + & 'should be present!!!') + END IF + +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: No case found for given precondition name') +END SELECT + ! engine -! -ierr = param%set( & - & key=TRIM(prefix)//"/engine", & - & VALUE=TRIM(engine)) -! +CALL Set(obj=param, prefix=prefix, key="engine", datatype="char", & +& VALUE=engine) + ! solverName -! -IF (PRESENT(solverName)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/solverName", & - & VALUE=solverName) -! +CALL Set(obj=param, prefix=prefix, key="solverName", datatype=1_I4B, & +& VALUE=solverName) + ! preconditionOption -! -IF (PRESENT(preconditionOption)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/preconditionOption", & - & VALUE=preconditionOption) -! +CALL Set(obj=param, prefix=prefix, key="preconditionOption", datatype=1_I4B, & +& VALUE=preconditionOption) + ! maxIter -! -IF (PRESENT(maxIter)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/maxIter", & - & VALUE=maxIter) -! +CALL Set(obj=param, prefix=prefix, key="maxIter", datatype=1_I4B, & +& VALUE=maxIter) + ! rtol -! -IF (PRESENT(rtol)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/rtol", & - & VALUE=rtol) -! +CALL Set(obj=param, prefix=prefix, key="rtol", datatype=1.0_DFP, & +& VALUE=rtol) + ! atol -! -IF (PRESENT(atol)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/atol", & - & VALUE=atol) -! +CALL Set(obj=param, prefix=prefix, key="atol", datatype=1.0_DFP, & +& VALUE=atol) + ! convergenceIn -! -IF (PRESENT(convergenceIn)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/convergenceIn", & - & VALUE=convergenceIn) -! +CALL Set(obj=param, prefix=prefix, key="convergenceIn", datatype=1_I4B, & +& VALUE=INPUT(option=convergenceIn, default=default_convergenceIn)) + ! convergenceType -! -IF (PRESENT(convergenceType)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/convergenceType", & - & VALUE=convergenceType) -! +CALL Set(obj=param, prefix=prefix, key="convergenceType", datatype=1_I4B, & +& VALUE=INPUT(option=convergenceType, default=default_convergenceType)) + ! relativeToRHS -! -IF (PRESENT(relativeToRHS)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/relativeToRHS", & - & VALUE=relativeToRHS) -! +CALL Set(obj=param, prefix=prefix, key="relativeToRHS", datatype=.TRUE., & +& VALUE=INPUT(option=relativeToRHS, default=default_relativeToRHS)) + ! KrylovSubspaceSize -! -IF (PRESENT(KrylovSubspaceSize)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/KrylovSubspaceSize", & - & VALUE=KrylovSubspaceSize) -! +CALL Set(obj=param, prefix=prefix, key="KrylovSubspaceSize", & +& datatype=1_I4B, & +& VALUE=INPUT(option=KrylovSubspaceSize, default=default_KrylovSubspaceSize)) + ! scale -! -IF (PRESENT(scale)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/scale", & - & VALUE=scale) -! +CALL Set(obj=param, prefix=prefix, key="scale", & +& datatype=1_I4B, & +& VALUE=INPUT(option=scale, default=default_scale)) + ! initx_zeros -! -IF (PRESENT(initx_zeros)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/initx_zeros", & - & VALUE=initx_zeros) -! +CALL Set(obj=param, prefix=prefix, key="initx_zeros", & +& datatype=.TRUE., & +& VALUE=INPUT(option=initx_zeros, default=default_initx_zeros)) + ! bicgstab_ell -! -IF (PRESENT(bicgstab_ell)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/bicgstab_ell", & - & VALUE=bicgstab_ell) -! +CALL Set(obj=param, prefix=prefix, key="bicgstab_ell", & +& datatype=1_I4B, & +& VALUE=INPUT(option=bicgstab_ell, default=default_bicgstab_ell)) + ! sor_omega -! -IF (PRESENT(sor_omega)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/sor_omega", & - & VALUE=sor_omega) -! +CALL Set(obj=param, prefix=prefix, key="sor_omega", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=sor_omega, default=default_sor_omega)) + ! p_name -! -IF (PRESENT(p_name)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/name", & - & VALUE=p_name) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/name", & +& datatype=1_I4B, & +& VALUE=p_name0) + ! p_ilu_lfil -! -IF (PRESENT(p_ilu_lfil)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ilu_lfil", & - & VALUE=p_ilu_lfil) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ilu_lfil", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_ilu_lfil, default=default_ilu_lfil)) + ! p_ilu_mbloc -! -IF (PRESENT(p_ilu_mbloc)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ilu_mbloc", & - & VALUE=p_ilu_mbloc) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ilu_mbloc", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_ilu_mbloc, default=default_ilu_mbloc)) + ! p_ilu_droptol -! -IF (PRESENT(p_ilu_droptol)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ilu_droptol", & - & VALUE=p_ilu_droptol) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ilu_droptol", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_ilu_droptol, default=default_ilu_droptol)) + ! p_ilu_permtol -! -IF (PRESENT(p_ilu_permtol)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ilu_permtol", & - & VALUE=p_ilu_permtol) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ilu_permtol", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_ilu_permtol, default=default_ilu_permtol)) + ! p_ilu_alpha -! -IF (PRESENT(p_ilu_alpha)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ilu_alpha", & - & VALUE=p_ilu_alpha) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ilu_alpha", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_ilu_alpha, default=default_ilu_alpha)) + ! p_ilu_fill -! -IF (PRESENT(p_ilu_fill)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ilu_fill", & - & VALUE=p_ilu_fill) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ilu_fill", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_ilu_fill, default=default_ilu_fill)) + ! p_ssor_omega -! -IF (PRESENT(p_ssor_omega)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/ssor_omega", & - & VALUE=p_ssor_omega) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/ssor_omega", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_ssor_omega, default=default_ssor_omega)) + ! p_hybrid_i -! -IF (PRESENT(p_hybrid_i)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/hybrid_i", & - & VALUE=p_hybrid_i) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/hybrid_i", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_hybrid_i, default=default_hybrid_i)) + ! p_hybrid_maxiter -! -IF (PRESENT(p_hybrid_maxiter)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/hybrid_maxiter", & - & VALUE=p_hybrid_maxiter) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/hybrid_maxiter", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_hybrid_maxiter, default=default_hybrid_maxiter)) + ! p_hybrid_tol -! -IF (PRESENT(p_hybrid_tol)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/hybrid_tol", & - & VALUE=p_hybrid_tol) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/hybrid_tol", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_hybrid_tol, default=default_hybrid_tol)) + ! p_hybrid_omega -! -IF (PRESENT(p_hybrid_omega)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/hybrid_omega", & - & VALUE=p_hybrid_omega) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/hybrid_omega", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_hybrid_omega, default=default_hybrid_omega)) + ! p_hybrid_ell -! -IF (PRESENT(p_hybrid_ell)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/hybrid_ell", & - & VALUE=p_hybrid_ell) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/hybrid_ell", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_hybrid_ell, default=default_hybrid_ell)) + ! p_hybrid_restart -! -IF (PRESENT(p_hybrid_restart)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/hybrid_restart", & - & VALUE=p_hybrid_restart) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/hybrid_restart", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_hybrid_restart, default=default_hybrid_restart)) + ! p_is_alpha -! -IF (PRESENT(p_is_alpha)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/is_alpha", & - & VALUE=p_is_alpha) +CALL Set(obj=param, prefix=prefix, key="/Precond/is_alpha", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_is_alpha, default=default_is_alpha)) + ! ! p_is_m -! -IF (PRESENT(p_is_m)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/is_m", & - & VALUE=p_is_m) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/is_m", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_is_m, default=default_is_m)) + ! p_sainv_drop -! -IF (PRESENT(p_sainv_drop)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/sainv_drop", & - & VALUE=p_sainv_drop) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/sainv_drop", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_sainv_drop, default=default_sainv_drop)) + ! p_saamg_unsym -! -IF (PRESENT(p_saamg_unsym)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/saamg_unsym", & - & VALUE=p_saamg_unsym) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/saamg_unsym", & +& datatype=.TRUE., & +& VALUE=INPUT(option=p_saamg_unsym, default=default_saamg_unsym)) + ! p_saamg_theta -! -IF (PRESENT(p_saamg_theta)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/saamg_theta", & - & VALUE=p_saamg_theta) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/saamg_theta", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_saamg_theta, default=default_saamg_theta)) + ! p_iluc_drop -! -IF (PRESENT(p_iluc_drop)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/iluc_drop", & - & VALUE=p_iluc_drop) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/iluc_drop", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_iluc_drop, default=default_iluc_drop)) + ! p_iluc_rate -! -IF (PRESENT(p_iluc_rate)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/iluc_rate", & - & VALUE=p_iluc_rate) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/iluc_rate", & +& datatype=1.0_DFP, & +& VALUE=INPUT(option=p_iluc_rate, default=default_iluc_rate)) + ! p_adds -! -IF (PRESENT(p_adds)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/adds", & - & VALUE=p_adds) -! +CALL Set(obj=param, prefix=prefix, key="/Precond/adds", & +& datatype=.TRUE., & +& VALUE=INPUT(option=p_adds, default=default_adds)) + ! p_adds_iter -! -IF (PRESENT(p_adds_iter)) & - & ierr = param%set( & - & key=TRIM(prefix)//"/Precond/adds_iter", & - & VALUE=p_adds_iter) +CALL Set(obj=param, prefix=prefix, key="/Precond/adds_iter", & +& datatype=1_I4B, & +& VALUE=INPUT(option=p_adds_iter, default=default_adds_iter)) -END PROCEDURE setAbstractLinSolverParam +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] SetAbstractLinSolverParam') +#endif +END PROCEDURE SetAbstractLinSolverParam END SUBMODULE SetMethods diff --git a/src/submodules/AbstractMeshField/src/AbstractMeshField_Class@ConstructorMethods.F90 b/src/submodules/AbstractMeshField/src/AbstractMeshField_Class@ConstructorMethods.F90 index 2e64592a1..c521f5525 100644 --- a/src/submodules/AbstractMeshField/src/AbstractMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractMeshField/src/AbstractMeshField_Class@ConstructorMethods.F90 @@ -50,10 +50,10 @@ ! CheckEssentialParam !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractFieldCheckEssentialParam +MODULE PROCEDURE AbstractMeshFieldCheckEssentialParam ! CHARACTER(*), PARAMETER :: myName = & - & "AbstractFieldCheckEssentialParam" + & "AbstractMeshFieldCheckEssentialParam" ! ! fieldType ! @@ -103,7 +103,7 @@ & CALL e%raiseError(modName//'::'//myName//" - "// & & 'rank should be present in param') ! -END PROCEDURE AbstractFieldCheckEssentialParam +END PROCEDURE AbstractMeshFieldCheckEssentialParam !---------------------------------------------------------------------------- ! Deallocate diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 index 11dd53ec2..a773171db 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 @@ -21,6 +21,43 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_SetParam +INTEGER(I4B) :: ii + +IF (PRESENT(dof_tPhysicalVars)) THEN + obj%dof_tPhysicalVars = dof_tPhysicalVars +END IF + +IF (PRESENT(dof_storageFMT)) THEN + obj%dof_storageFMT = dof_storageFMT +END IF + +IF (PRESENT(dof_spaceCompo)) THEN + obj%dof_spaceCompo = dof_spaceCompo +END IF + +IF (PRESENT(dof_timeCompo)) THEN + obj%dof_timeCompo = dof_timeCompo +END IF + +IF (PRESENT(dof_tNodes)) THEN + obj%dof_tNodes = dof_tNodes +END IF + +IF (PRESENT(dof_names_char)) THEN + IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) + ALLOCATE (obj%dof_names_char(SIZE(dof_names_char))) + DO ii = 1, SIZE(dof_names_char) + obj%dof_names_char(ii) = obj%dof_names_char(ii) + END DO +END IF + +END PROCEDURE anf_SetParam + !---------------------------------------------------------------------------- ! Display !---------------------------------------------------------------------------- @@ -240,9 +277,6 @@ MODULE PROCEDURE AbstractNodeFieldInitiate CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP] :: This routine is under development') - CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) IF (obj%dof_tPhysicalVars .EQ. 0_I4B) THEN diff --git a/src/submodules/CMakeLists.txt b/src/submodules/CMakeLists.txt index d279480d4..7855c6d1a 100644 --- a/src/submodules/CMakeLists.txt +++ b/src/submodules/CMakeLists.txt @@ -42,6 +42,9 @@ INCLUDE(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) # VTKFile INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) +# Toml +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) + # Element INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Element/CMakeLists.txt) diff --git a/src/submodules/Domain/src/Domain_Class@ConstructorMethods.F90 b/src/submodules/Domain/src/Domain_Class@ConstructorMethods.F90 index 586760c80..5674f43de 100644 --- a/src/submodules/Domain/src/Domain_Class@ConstructorMethods.F90 +++ b/src/submodules/Domain/src/Domain_Class@ConstructorMethods.F90 @@ -106,7 +106,9 @@ ! BUG CALL e%raiseDebug(modName//'::'//myName//'-'// & & 'There should be better way to deallocate obj%meshList...') -IF (ALLOCATED(obj%meshList)) DEALLOCATE (obj%meshList) +IF (ALLOCATED(obj%meshList)) THEN + DEALLOCATE (obj%meshList) +END IF IF (ALLOCATED(obj%nodeCoord)) DEALLOCATE (obj%nodeCoord) IF (ALLOCATED(obj%local_nptrs)) DEALLOCATE (obj%local_nptrs) IF (ALLOCATED(obj%global_nptrs)) DEALLOCATE (obj%global_nptrs) diff --git a/src/submodules/Domain/src/Domain_Class@GetMethods.F90 b/src/submodules/Domain/src/Domain_Class@GetMethods.F90 index 958afea09..964395e66 100644 --- a/src/submodules/Domain/src/Domain_Class@GetMethods.F90 +++ b/src/submodules/Domain/src/Domain_Class@GetMethods.F90 @@ -387,6 +387,18 @@ END IF END PROCEDURE Domain_GetNodeCoord +!---------------------------------------------------------------------------- +! getNodeCoord +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Domain_GetNodeCoord2 +INTEGER(I4B) :: localNode(SIZE(globalNode)) +INTEGER(I4B) :: nsd +localNode = obj%GetLocalNodeNumber(globalNode=globalNode) +nsd = SIZE(nodeCoord, 1) +nodeCoord = nodeCoord(1:nsd, localNode) +END PROCEDURE Domain_GetNodeCoord2 + !---------------------------------------------------------------------------- ! getNodeCoordPointer !---------------------------------------------------------------------------- @@ -553,7 +565,7 @@ IF (dim .GT. 3) THEN CALL e%raiseError(modName//"::"//myName//" - "// & - & "[ARG ERROR] Dim of the mesh should be in [0,1,2,3]"// & + & "[ARG ERROR] :: Dim of the mesh should be in [0,1,2,3]"// & & " given dim is equal to "//tostring(dim)) RETURN END IF diff --git a/src/submodules/ExceptionHandler/src/ExceptionHandler_Class@Constructor.F90 b/src/submodules/ExceptionHandler/src/ExceptionHandler_Class@Constructor.F90 index 2fb94970e..7434e3b7e 100644 --- a/src/submodules/ExceptionHandler/src/ExceptionHandler_Class@Constructor.F90 +++ b/src/submodules/ExceptionHandler/src/ExceptionHandler_Class@Constructor.F90 @@ -158,13 +158,13 @@ NULLIFY (obj%surrogate) obj%stopOnError = tmpE%stopOnError obj%logFileActive = tmpE%logFileActive -obj%quiet = tmpE%quiet obj%logFileUnit = tmpE%logFileUnit obj%nInfo = tmpE%nInfo obj%nWarn = tmpE%nWarn +obj%nDebug = tmpE%nDebug obj%nError = tmpE%nError obj%nFatal = tmpE%nFatal -obj%nDebug = tmpE%nDebug +obj%quiet = tmpE%quiet obj%verbose = tmpE%verbose obj%lastMesg = tmpE%lastMesg NULLIFY (tmpE) diff --git a/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 b/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 index fb3df8ecc..8f98b273d 100644 --- a/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 +++ b/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 @@ -18,8 +18,8 @@ SUBMODULE(FortranFile_Class) ConstructorMethods USE BaseMethod IMPLICIT NONE -CHARACTER(maxStrLen) :: emesg, iomsg -INTEGER(I4B) :: ioerr +! CHARACTER(maxStrLen) :: emesg, iomsg +! INTEGER(I4B) :: ioerr CONTAINS !---------------------------------------------------------------------------- @@ -36,6 +36,9 @@ TYPE(String) :: fpath, fname, fext, file_ LOGICAL(LGT) :: ostat INTEGER(I4B) :: oldcnt, ierr + +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr ! ! Initialize data ! @@ -317,6 +320,9 @@ MODULE PROCEDURE ff_Deallocate LOGICAL(LGT) :: bool +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr + !Close the file bool = .FALSE. IF (PRESENT(delete)) bool = delete @@ -366,6 +372,8 @@ CHARACTER(3) :: padvar INTEGER(I4B) :: reclval TYPE(String) :: path, filename, ext +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr !Get the appropriate clause values for the OPEN statement IF (obj%initstat) THEN @@ -510,6 +518,8 @@ MODULE PROCEDURE ff_close CHARACTER(*), PARAMETER :: myName = 'ff_close' +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr ! IF (obj%initstat) THEN IF (obj%isOpen()) THEN @@ -539,6 +549,8 @@ MODULE PROCEDURE ff_delete CHARACTER(*), PARAMETER :: myName = 'ff_delete' TYPE(String) :: path, filename, ext +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr IF (obj%initstat) THEN IF (obj%isOpen()) THEN @@ -590,6 +602,9 @@ MODULE PROCEDURE ff_backspace CHARACTER(*), PARAMETER :: myName = 'ff_backspace' +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr + IF (obj%initstat) THEN IF (obj%isOpen()) THEN BACKSPACE (UNIT=obj%unitno, IOSTAT=ioerr, IOMSG=iomsg) @@ -617,15 +632,37 @@ MODULE PROCEDURE ff_rewind CHARACTER(*), PARAMETER :: myName = 'ff_rewind' +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName //'::'//myName// ' - '// & + & '[START] Rewind()') +#endif + +#ifdef Darwin_SYSTEM +CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[BUG] :: REWIND() function does not work with GNU Fortran. ' // & + & 'We are working on this issue. ') +#else + IF (obj%initstat) THEN IF (obj%isOpen()) THEN + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[1] ' // tostring(obj%unitno) ) REWIND (UNIT=obj%unitno, IOSTAT=ioerr, IOMSG=iomsg) + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[2]') CALL obj%setEOFstat(.FALSE.) + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[3]') IF (ioerr /= 0) THEN WRITE (emesg, '(a,i4,a,i4,a)') 'Error rewinding file (UNIT=', & & obj%unitno, ') IOSTAT=', ioerr, ' IOMSG='//TRIM(iomsg) CALL e%raiseError(modName//'::'//myName//' - '//emesg) END IF + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[4]') ELSE WRITE (emesg, '(a,i4,a)') 'Cannot rewind file (UNIT=', obj%unitno, & & '). File not is not open!' @@ -635,6 +672,14 @@ CALL e%raiseError(modName//'::'//myName//' - '// & & 'Cannot rewind file! File object has not been initialized!') END IF + +#endif + + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName //'::'//myName// ' - '// & + & '[END] Rewind()') +#endif END PROCEDURE ff_rewind !---------------------------------------------------------------------------- diff --git a/src/submodules/LinSolver/src/LIS_SOLVE.inc b/src/submodules/LinSolver/src/LIS_SOLVE.inc index 0083d99db..26ddaf70c 100644 --- a/src/submodules/LinSolver/src/LIS_SOLVE.inc +++ b/src/submodules/LinSolver/src/LIS_SOLVE.inc @@ -23,7 +23,7 @@ SUBROUTINE _SUBROUTINE_NAME(obj, sol, rhs) ! Internal variables ! CHARACTER(*), PARAMETER :: myName = _MY_NAME - INTEGER(I4B) :: n, ii + INTEGER(I4B) :: n REAL(DFP), ALLOCATABLE :: diag(:) CLASS(AbstractMatrixField_), POINTER :: Amat diff --git a/src/submodules/LinSolver/src/LinSolver_Class@GetMethods.F90 b/src/submodules/LinSolver/src/LinSolver_Class@GetMethods.F90 index 6fc9250b1..944075079 100644 --- a/src/submodules/LinSolver/src/LinSolver_Class@GetMethods.F90 +++ b/src/submodules/LinSolver/src/LinSolver_Class@GetMethods.F90 @@ -21,11 +21,23 @@ CONTAINS !---------------------------------------------------------------------------- -! getLinSolverCodeFromName +! GetPrefix !---------------------------------------------------------------------------- -MODULE PROCEDURE ls_getLinSolverCodeFromName -SELECT CASE (TRIM(name)) +MODULE PROCEDURE ls_GetPrefix +ans = myprefix +END PROCEDURE ls_GetPrefix + + +!---------------------------------------------------------------------------- +! GetLinSolverCodeFromName +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ls_GetLinSolverCodeFromName +TYPE(String) :: astr +astr = UpperCase(name) + +SELECT CASE (astr%chars()) CASE ("SUPERLU") !1 ans = LIS_SUPERLU CASE ("CG") !1 @@ -85,13 +97,14 @@ CASE ("DQGMRES") !28 ans = LIS_DQGMRES END SELECT -END PROCEDURE ls_getLinSolverCodeFromName +astr = "" +END PROCEDURE ls_GetLinSolverCodeFromName !---------------------------------------------------------------------------- -! getLinSolverNameFromCode +! GetLinSolverNameFromCode !---------------------------------------------------------------------------- -MODULE PROCEDURE ls_getLinSolverNameFromCode +MODULE PROCEDURE ls_GetLinSolverNameFromCode SELECT CASE (name) CASE (LIS_SUPERLU) ans = "SUPERLU" !1 @@ -152,14 +165,14 @@ CASE (LIS_DQGMRES) ans = "DQGMRES" !28 END SELECT -END PROCEDURE ls_getLinSolverNameFromCode +END PROCEDURE ls_GetLinSolverNameFromCode !---------------------------------------------------------------------------- -! getLinSolverParam +! GetLinSolverParam !---------------------------------------------------------------------------- -MODULE PROCEDURE getLinSolverParam -CALL getAbstractLinSolverParam( & +MODULE PROCEDURE GetLinSolverParam +CALL GetAbstractLinSolverParam( & & param=param, & & prefix=myPrefix, & & solverName=solverName, & @@ -199,7 +212,7 @@ & p_adds=p_adds, & & p_adds_iter=p_adds_iter & & ) -END PROCEDURE getLinSolverParam +END PROCEDURE GetLinSolverParam !---------------------------------------------------------------------------- ! diff --git a/src/submodules/LinSolver/src/LinSolver_Class@IOMethods.F90 b/src/submodules/LinSolver/src/LinSolver_Class@IOMethods.F90 index ffdfe0c9d..c8184c77f 100644 --- a/src/submodules/LinSolver/src/LinSolver_Class@IOMethods.F90 +++ b/src/submodules/LinSolver/src/LinSolver_Class@IOMethods.F90 @@ -47,8 +47,10 @@ obj%isInitiated = .FALSE. CALL param%initiate() -CALL setLinSolverParam( & +CALL SetAbstractLinSolverParam( & & param=param, & + & prefix=obj%GetPrefix(), & + & engine=myengine, & & solverName=obj%solverName,& & preconditionOption=obj%preconditionOption, & & convergenceIn=obj%convergenceIn, & diff --git a/src/submodules/LinSolver/src/LinSolver_Class@SetMethods.F90 b/src/submodules/LinSolver/src/LinSolver_Class@SetMethods.F90 index e6cb3590a..abbc4cd71 100644 --- a/src/submodules/LinSolver/src/LinSolver_Class@SetMethods.F90 +++ b/src/submodules/LinSolver/src/LinSolver_Class@SetMethods.F90 @@ -74,6 +74,11 @@ END SUBROUTINE AllocateWorkSpace INTEGER(I4B) :: s(2) INTEGER(I4B) :: solverName +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ls_Set()') +#endif + s = Amat%SHAPE() CALL obj%SetParam(Amat=Amat, & & localNumColumn=s(2), localNumRow=s(1), & @@ -87,228 +92,12 @@ END SUBROUTINE AllocateWorkSpace & solverName=solverName, & & IPAR=obj%IPAR) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ls_Set()') +#endif END PROCEDURE ls_Set -!---------------------------------------------------------------------------- -! setLinSolverParam -!---------------------------------------------------------------------------- - -MODULE PROCEDURE setLinSolverParam -CHARACTER(*), PARAMETER :: myName = "setLinSolverParam" -INTEGER(I4B) :: p_name0 - -IF (.NOT. PRESENT(solverName)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'solverName should be present') -END IF - -IF (solverName .EQ. LIS_SOR) THEN - IF (.NOT. PRESENT(sor_omega)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'For solverName LIS_SOR sor_omega should be present') - END IF -END IF - -IF (solverName .EQ. LIS_BICGSTABL) THEN - IF (.NOT. PRESENT(bicgstab_ell)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'For solverName LIS_BICGSTABL bicgstab_ell should be present') - END IF -END IF - -IF (.NOT. PRESENT(preconditionOption)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'preconditionOption should be present') -END IF - -p_name0 = input(option=p_name, default=PRECOND_NONE) - -IF (preconditionOption .NE. PRECOND_NONE) THEN - IF (.NOT. PRESENT(p_name)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'preconditionOption is active, therefore, '// & - & 'precondition name (p_name) should be present') - END IF -END IF - -SELECT CASE (p_name0) -CASE( PRECOND_NONE ) - !! Do nothing -CASE (PRECOND_ILUT) - IF (.NOT. PRESENT(p_ilu_droptol) .OR. & - & .NOT. PRESENT(p_ilu_lfil)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILUT (sparsekit) p_ilu_droptol and p_ilu_lfil should be present!!!') - END IF -CASE (PRECOND_ILUTP) - IF (.NOT. PRESENT(p_ilu_droptol) .OR. & - & .NOT. PRESENT(p_ilu_lfil) .OR. & - & .NOT. PRESENT(p_ilu_permtol) .OR. & - & .NOT. PRESENT(p_ilu_mbloc)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILUTP (sparsekit) p_ilu_droptol, p_ilu_lfil, p_ilu_permtol, '// & - & 'p_ilu_mbloc should be present!!!') - END IF -CASE (PRECOND_ILUD) - IF (.NOT. PRESENT(p_ilu_droptol) .OR. & - & .NOT. PRESENT(p_ilu_alpha)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILUTP (sparsekit) p_ilu_droptol and p_ilu_alpha should be present!!!') - END IF -CASE (PRECOND_ILUDP) - IF (.NOT. PRESENT(p_ilu_droptol) .OR. & - & .NOT. PRESENT(p_ilu_alpha) .OR. & - & .NOT. PRESENT(p_ilu_permtol) .OR. & - & .NOT. PRESENT(p_ilu_mbloc)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILUDP (sparsekit) p_ilu_droptol, p_ilu_alpha, p_ilu_permtol, '// & - & 'p_ilu_mbloc should be present!!!') - END IF -CASE (PRECOND_ILUK) - IF (.NOT. PRESENT(p_ilu_lfil)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILUK (sparsekit) p_ilu_lfil should be present!!!') - END IF -! -! LIS LIB -! -CASE (PRECOND_ILU) - IF (.NOT. PRESENT(p_ilu_fill)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILU (LIS) p_ilu_fill should be present!!!') - END IF -CASE (PRECOND_SSOR) - IF (.NOT. PRESENT(p_ssor_omega)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_SSOR (LIS) p_ssor_omega should be present!!!') - END IF -CASE (PRECOND_HYBRID) - - IF (.NOT. PRESENT(p_hybrid_i) .OR. & - & .NOT. PRESENT(p_hybrid_tol) .OR. & - & .NOT. PRESENT(p_hybrid_maxiter) & - & ) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_HYBRID (LIS) p_hybrid_i p_hybrid_maxiter p_hybrid_tol'// & - & ' should be present!!!') - END IF - - IF (p_hybrid_i .EQ. LIS_SOR) THEN - IF (.NOT. PRESENT(p_hybrid_omega)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_HYBRID (LIS) and p_hybrid_i=LIS_SOR, p_hybrid_omega'// & - & ' should be present!!!') - END IF - END IF - - IF (p_hybrid_i .EQ. LIS_BICGSTABL) THEN - IF (.NOT. PRESENT(p_hybrid_ell)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_HYBRID (LIS) and p_hybrid_i=LIS_BICGSTABL,'// & - & ' p_hybrid_ell should be present!!!') - END IF - END IF - - IF (ANY(p_hybrid_i .EQ. [LIS_GMRES, LIS_ORTHOMIN, LIS_FGMRES])) THEN - IF (.NOT. PRESENT(p_hybrid_restart)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_HYBRID (LIS), '// & - & 'and p_hybrid_i=LIS_GMRES LIS_ORTHOMIN LIS_FGMRES, '// & - & 'p_hybrid_restart should be present!!!') - END IF - END IF - -CASE (PRECOND_IS) - IF (.NOT. PRESENT(p_is_alpha) .OR. & - & .NOT. PRESENT(p_is_m)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_IS (LIS) p_is_alpha, p_is_m should be present!!!') - END IF - -CASE (PRECOND_SAINV) - IF (.NOT. PRESENT(p_sainv_drop)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_SAINV (LIS) p_sainv_drop should be present!!!') - END IF - -CASE (PRECOND_SAAMG) - - IF ( & - & .NOT. PRESENT(p_saamg_theta) .OR. & - & .NOT. PRESENT(p_saamg_unsym)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_SAAMG (LIS) p_saamg_theta, p_saamg_unsym'// & - & 'should be present!!!') - END IF - -CASE (PRECOND_ILUC) - - IF ( & - & .NOT. PRESENT(p_iluc_drop) .OR. & - & .NOT. PRESENT(p_iluc_rate)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ILUC (LIS) p_iluc_drop, p_iluc_rate'// & - & 'should be present!!!') - END IF - -CASE (PRECOND_ADDS) - - IF ( & - & .NOT. PRESENT(p_adds) .OR. & - & .NOT. PRESENT(p_adds_iter)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'for PRECOND_ADDS (LIS) p_adds, p_adds_iter'// & - & 'should be present!!!') - END IF - -CASE DEFAULT - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'No case found for given precondition name') -END SELECT - -CALL setAbstractLinSolverParam( & -& param=param, & -& prefix=myprefix, & -& engine="NATIVE_SERIAL", & -& solverName=solverName, & -& preconditionOption=preconditionOption, & -& p_name=p_name0, & -& convergenceIn=INPUT(option=convergenceIn, default=default_convergenceIn), & -& convergenceType=INPUT(option=convergenceType, default=default_convergenceType), & -& maxIter=INPUT(option=maxIter, default=default_maxIter), & -& relativeToRHS=INPUT(option=relativeToRHS, default=default_relativeToRHS), & -& KrylovSubspaceSize=INPUT(option=KrylovSubspaceSize, default=default_KrylovSubspaceSize), & -& rtol=INPUT(option=rtol, default=default_rtol), & -& atol=INPUT(option=atol, default=default_atol), & -& scale=Input(option=scale, default=default_scale), & -& initx_zeros=input(option=initx_zeros, default=default_initx_zeros), & -& bicgstab_ell=input(option=bicgstab_ell, default=default_bicgstab_ell), & -& sor_omega=input(option=sor_omega, default=default_sor_omega), & -& p_ilu_lfil=input(option=p_ilu_lfil, default=default_ilu_lfil), & -& p_ilu_mbloc=input(option=p_ilu_mbloc, default=default_ilu_mbloc), & -& p_ilu_droptol=input(option=p_ilu_droptol, default=default_ilu_droptol), & -& p_ilu_permtol=input(option=p_ilu_permtol, default=default_ilu_permtol), & -& p_ilu_alpha=input(option=p_ilu_alpha, default=default_ilu_alpha), & -& p_ilu_fill=input(option=p_ilu_fill, default=default_ilu_fill), & -& p_ssor_omega=input(option=p_ssor_omega, default=default_ssor_omega), & -& p_hybrid_i=input(option=p_hybrid_i, default=default_hybrid_i), & -& p_hybrid_maxiter=input(option=p_hybrid_maxiter,default=default_hybrid_maxiter), & -& p_hybrid_tol=input(option=p_hybrid_tol, default=default_hybrid_tol), & -& p_hybrid_omega=input(option=p_hybrid_omega, default=default_hybrid_omega), & -& p_hybrid_ell=input(option=p_hybrid_ell, default=default_hybrid_ell), & -& p_hybrid_restart=input(option=p_hybrid_restart,default=default_hybrid_restart), & -& p_is_alpha=input(option=p_is_alpha, default=default_is_alpha), & -& p_is_m=input(option=p_is_m, default=default_is_m), & -& p_sainv_drop=input(option=p_sainv_drop, default=default_sainv_drop), & -& p_saamg_unsym=input(option=p_saamg_unsym, default=default_saamg_unsym), & -& p_saamg_theta=input(option=p_saamg_theta, default=default_saamg_theta), & -& p_iluc_drop=input(option=p_iluc_drop, default=default_iluc_drop), & -& p_iluc_rate=input(option=p_iluc_rate, default=default_iluc_rate), & -& p_adds=input(option=p_adds, default=default_adds), & -& p_adds_iter=input(option=p_adds_iter, default=default_adds_iter) & -& ) -END PROCEDURE setLinSolverParam - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/LinSolver/src/LinSolver_Class@SolveMethods.F90 b/src/submodules/LinSolver/src/LinSolver_Class@SolveMethods.F90 index 76bd94b3d..02d72e285 100644 --- a/src/submodules/LinSolver/src/LinSolver_Class@SolveMethods.F90 +++ b/src/submodules/LinSolver/src/LinSolver_Class@SolveMethods.F90 @@ -33,6 +33,11 @@ SUBROUTINE PERFORM_TASK(Amat, y, x, ierr, myName) ! ! main ! +#ifdef DEBUG_VER + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] PERFORM_TASK()') +#endif + SELECT CASE (ierr) CASE (1) CALL Amat%Matvec(y=y, x=x, isTranspose=.FALSE.) @@ -47,6 +52,11 @@ SUBROUTINE PERFORM_TASK(Amat, y, x, ierr, myName) ! The preconditioners are inside the Amat CALL Amat%ILUSOLVE(sol=y, rhs=x, isTranspose=.TRUE.) END SELECT + +#ifdef DEBUG_VER + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] PERFORM_TASK()') +#endif END SUBROUTINE PERFORM_TASK !---------------------------------------------------------------------------- @@ -153,7 +163,7 @@ END SUBROUTINE DisplayConvergence ! CHARACTER(*), PARAMETER :: myName = "ls_Solve" REAL(DFP), POINTER :: rhsvar(:), solvar(:) -INTEGER(I4B) :: ii, info +INTEGER(I4B) :: info INTEGER(I4B) :: solverName LOGICAL(LGT) :: isInitiated0 CLASS(AbstractMatrixField_), POINTER :: Amat diff --git a/src/submodules/LinSolverLis/src/LinSolverLis_Class@ConstructorMethods.F90 b/src/submodules/LinSolverLis/src/LinSolverLis_Class@ConstructorMethods.F90 index a0a3a6bbe..fa5f91b21 100644 --- a/src/submodules/LinSolverLis/src/LinSolverLis_Class@ConstructorMethods.F90 +++ b/src/submodules/LinSolverLis/src/LinSolverLis_Class@ConstructorMethods.F90 @@ -27,7 +27,7 @@ MODULE PROCEDURE ls_Initiate #include "lisf.h" CHARACTER(*), PARAMETER :: myName = "ls_Initiate" -INTEGER(I4B) :: comm, ierr +INTEGER(I4B) :: ierr INTEGER(I4B) :: solverName INTEGER(I4B) :: preconditionOption INTEGER(I4B) :: convergenceIn diff --git a/src/submodules/LinSolverLis/src/LinSolverLis_Class@SolveMethods.F90 b/src/submodules/LinSolverLis/src/LinSolverLis_Class@SolveMethods.F90 index 84cab21c9..867e9f9af 100644 --- a/src/submodules/LinSolverLis/src/LinSolverLis_Class@SolveMethods.F90 +++ b/src/submodules/LinSolverLis/src/LinSolverLis_Class@SolveMethods.F90 @@ -123,7 +123,6 @@ END SUBROUTINE DisplayConvergence MODULE PROCEDURE ls_Solve #include "lisf.h" CHARACTER(*), PARAMETER :: myName = "ls_Solve" -INTEGER(I4B) :: ii INTEGER(I4B) :: ierr IF (.NOT. obj%isInitiated) THEN @@ -153,6 +152,7 @@ END SUBROUTINE DisplayConvergence END IF CALL lis_solve(obj%Amat%lis_ptr, rhs%lis_ptr, sol%lis_ptr, obj%lis_solver, ierr) + CALL chkerr(ierr) END PROCEDURE ls_Solve diff --git a/src/submodules/MSHFile/src/MSHFile_Class@ConstructorMethods.F90 b/src/submodules/MSHFile/src/MSHFile_Class@ConstructorMethods.F90 index 6245f3106..96f50c581 100644 --- a/src/submodules/MSHFile/src/MSHFile_Class@ConstructorMethods.F90 +++ b/src/submodules/MSHFile/src/MSHFile_Class@ConstructorMethods.F90 @@ -33,23 +33,50 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE msh_Deallocate +INTEGER(I4B) :: ii +CHARACTER(*), PARAMETER :: myName="msh_Deallocate()" + CALL obj%FORMAT%DEALLOCATE() CALL obj%PhysicalNames%DEALLOCATE() CALL obj%Nodes%DEALLOCATE() CALL obj%Elements%DEALLOCATE() -IF (ALLOCATED(obj%PointEntities)) DEALLOCATE (obj%PointEntities) -IF (ALLOCATED(obj%CurveEntities)) DEALLOCATE (obj%CurveEntities) -IF (ALLOCATED(obj%SurfaceEntities)) DEALLOCATE (obj%SurfaceEntities) -IF (ALLOCATED(obj%VolumeEntities)) DEALLOCATE (obj%VolumeEntities) +IF (ALLOCATED(obj%PointEntities)) THEN + DO ii = 1, SIZE(obj%PointEntities) + CALL obj%PointEntities(ii)%DEALLOCATE() + END DO + DEALLOCATE (obj%PointEntities) +END IF + +IF (ALLOCATED(obj%CurveEntities)) THEN + DO ii = 1, SIZE(obj%CurveEntities) + CALL obj%CurveEntities(ii)%DEALLOCATE() + END DO + DEALLOCATE (obj%CurveEntities) +END IF + +IF (ALLOCATED(obj%SurfaceEntities)) THEN + DO ii = 1, SIZE(obj%SurfaceEntities) + CALL obj%SurfaceEntities(ii)%DEALLOCATE() + END DO + DEALLOCATE (obj%SurfaceEntities) +END IF + +IF (ALLOCATED(obj%VolumeEntities)) THEN + DO ii = 1, SIZE(obj%VolumeEntities) + CALL obj%VolumeEntities(ii)%DEALLOCATE() + END DO + DEALLOCATE (obj%VolumeEntities) +END IF + obj%nsd = 0 IF (ASSOCIATED(obj%buffer)) DEALLOCATE (obj%buffer) NULLIFY (obj%buffer) CALL TxtFileDeallocate(obj, Delete) END PROCEDURE msh_Deallocate -! !---------------------------------------------------------------------------- -! ! msh4 -! !---------------------------------------------------------------------------- +!---------------------------------------------------------------------------- +! msh4 +!---------------------------------------------------------------------------- ! MODULE PROCEDURE msh_constuctor1 ! CALL ans%Initiate( Path, FileName, Extension, NSD ) diff --git a/src/submodules/MSHFile/src/MSHFile_Class@IOMethods.F90 b/src/submodules/MSHFile/src/MSHFile_Class@IOMethods.F90 index 674be0e65..b830bb0b1 100644 --- a/src/submodules/MSHFile/src/MSHFile_Class@IOMethods.F90 +++ b/src/submodules/MSHFile/src/MSHFile_Class@IOMethods.F90 @@ -27,8 +27,8 @@ MODULE PROCEDURE msh_Import CHARACTER(*), PARAMETER :: myName = "msh_Import" -CALL e%raiseError(modName//'::'//myName//" - "// & - & 'This routine is under condtruction') +CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[WIP ERROR] :: This routine is under condtruction') END PROCEDURE msh_Import !---------------------------------------------------------------------------- @@ -40,17 +40,17 @@ INTEGER(I4B) :: ii, tsize, tNodes, count_ REAL(DFP), ALLOCATABLE :: nodeCoord(:, :) INTEGER(I4B), ALLOCATABLE :: local_nptrs(:) -TYPE(String) :: dsetname +TYPE(String) :: dSetname !> main -dsetname = TRIM(group) +dSetname = TRIM(group) !>check IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file is not opened') END IF !>check IF (.NOT. hdf5%isWrite()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'HDF5 file does not have write permission') END IF @@ -60,22 +60,22 @@ count_ = 0 local_nptrs = 0 -CALL hdf5%WRITE(dsetname=dsetname%chars()//"/NSD", vals=obj%nsd) -CALL ExportMeshFormat(obj, hdf5, dsetname) +CALL hdf5%WRITE(dSetname=dSetname%chars()//"/NSD", vals=obj%nsd) +CALL ExportMeshFormat(obj, hdf5, dSetname) IF (obj%physicalNames%isInitiated) & - & CALL ExportMeshPhysicalNames(obj, hdf5, dsetname) -CALL ExportMeshNodeInfo(obj, hdf5, dsetname) -CALL ExportMeshElementInfo(obj, hdf5, dsetname) + & CALL ExportMeshPhysicalNames(obj, hdf5, dSetname) +CALL ExportMeshNodeInfo(obj, hdf5, dSetname) +CALL ExportMeshElementInfo(obj, hdf5, dSetname) IF (ALLOCATED(obj%pointEntities)) THEN tsize = SIZE(obj%pointEntities) ELSE tsize = 0 END IF -CALL hdf5%WRITE(dsetname=dsetname%chars()// & +CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/numPointEntities", vals=tsize) DO ii = 1, tsize CALL ExportMeshEntity(obj%pointEntities(ii), hdf5, & - & dsetname=dsetname%chars()//"/pointEntities_"// & + & dSetname=dSetname%chars()//"/pointEntities_"// & & TRIM(str(ii, .TRUE.)), nsd=obj%nsd) CALL getNodeCoord(obj=obj%pointEntities(ii), nodeCoord=nodeCoord, & & local_nptrs=local_nptrs, count_=count_) @@ -85,11 +85,11 @@ ELSE tsize = 0 END IF -CALL hdf5%WRITE(dsetname=dsetname%chars()// & +CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/numCurveEntities", vals=tsize) DO ii = 1, tsize CALL ExportMeshEntity(obj%curveEntities(ii), hdf5, & - & dsetname=dsetname%chars()//"/curveEntities_"// & + & dSetname=dSetname%chars()//"/curveEntities_"// & & TRIM(str(ii, .TRUE.)), nsd=obj%nsd) CALL getNodeCoord(obj=obj%curveEntities(ii), nodeCoord=nodeCoord, & & local_nptrs=local_nptrs, count_=count_) @@ -99,11 +99,11 @@ ELSE tsize = 0 END IF -CALL hdf5%WRITE(dsetname=dsetname%chars()// & +CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/numSurfaceEntities", vals=tsize) DO ii = 1, tsize CALL ExportMeshEntity(obj%surfaceEntities(ii), hdf5, & - & dsetname=dsetname%chars()//"/surfaceEntities_"// & + & dSetname=dSetname%chars()//"/surfaceEntities_"// & & TRIM(str(ii, .TRUE.)), nsd=obj%nsd) CALL getNodeCoord(obj=obj%surfaceEntities(ii), nodeCoord=nodeCoord, & & local_nptrs=local_nptrs, count_=count_) @@ -113,18 +113,18 @@ ELSE tsize = 0 END IF -CALL hdf5%WRITE(dsetname=dsetname%chars()// & +CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/numVolumeEntities", vals=tsize) DO ii = 1, tsize CALL ExportMeshEntity(obj%volumeEntities(ii), hdf5, & - & dsetname=dsetname%chars()//"/volumeEntities_"// & + & dSetname=dSetname%chars()//"/volumeEntities_"// & & TRIM(str(ii, .TRUE.)), nsd=obj%nsd) CALL getNodeCoord(obj=obj%volumeEntities(ii), nodeCoord=nodeCoord, & & local_nptrs=local_nptrs, count_=count_) END DO -CALL hdf5%WRITE(dsetname=dsetname%chars()//"/nodeCoord", & +CALL hdf5%WRITE(dSetname=dSetname%chars()//"/nodeCoord", & &vals=nodeCoord) -CALL hdf5%WRITE(dsetname=dsetname%chars()//"/local_nptrs", & +CALL hdf5%WRITE(dSetname=dSetname%chars()//"/local_nptrs", & &vals=local_nptrs) IF (ALLOCATED(nodeCoord)) DEALLOCATE (nodeCoord) END PROCEDURE msh_Export_hdf5 @@ -133,18 +133,18 @@ ! ExportMeshFormat !---------------------------------------------------------------------------- -SUBROUTINE ExportMeshFormat(obj, hdf5, dsetname) +SUBROUTINE ExportMeshFormat(obj, hdf5, dSetname) CLASS(MSHFile_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 - TYPE(String), INTENT(IN) :: dsetname + TYPE(String), INTENT(IN) :: dSetname ! Writing mesh format - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/version", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/version", & & vals=obj%FORMAT%getVersion()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/majorVersion", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/majorVersion", & & vals=obj%FORMAT%getMajorVersion()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/minorVersion", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/minorVersion", & & vals=obj%FORMAT%getMinorVersion()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/engine", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/engine", & & vals=string("GMSH 4.1 0 8")) END SUBROUTINE ExportMeshFormat @@ -152,40 +152,40 @@ END SUBROUTINE ExportMeshFormat ! ExportMeshPhysicalNames !---------------------------------------------------------------------------- -SUBROUTINE ExportMeshPhysicalNames(obj, hdf5, dsetname) +SUBROUTINE ExportMeshPhysicalNames(obj, hdf5, dSetname) CLASS(MSHFile_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 - TYPE(String), INTENT(IN) :: dsetname + TYPE(String), INTENT(IN) :: dSetname ! Internal variables INTEGER(I4B) :: ii, tsize ! Physical Names tsize = obj%physicalNames%getTotalPhysicalEntities() - CALL hdf5%WRITE(dsetname=dsetname%chars()// & + CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/PhysicalNames/totalPhysicalEntities", & & vals=tsize) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/PhysicalNames/NSD", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/PhysicalNames/NSD", & & vals=obj%physicalNames%getNSD()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/PhysicalNames/tag", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/PhysicalNames/tag", & & vals=obj%physicalNames%getPhysicalTags()) - CALL hdf5%WRITE(dsetname=dsetname%chars()// & + CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/PhysicalNames/numElements", & & vals=obj%physicalNames%getNumElements()) - CALL hdf5%WRITE(dsetname=dsetname%chars()// & + CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/PhysicalNames/numNodes", & & vals=obj%physicalNames%getNumNodes()) - CALL hdf5%WRITE(dsetname=dsetname%chars()// & + CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/PhysicalNames/physicalName", & & vals=obj%physicalNames%getPhysicalNames()) DO ii = 1, tsize - CALL hdf5%WRITE(dsetname=dsetname%chars()// & + CALL hdf5%WRITE(dSetname=dSetname%chars()// & & "/PhysicalNames/entities_" & & //TRIM(str(ii, .TRUE.)), & & vals=obj%physicalNames%getEntities(indx=ii)) @@ -196,17 +196,17 @@ END SUBROUTINE ExportMeshPhysicalNames ! ExportMeshNodeInfo !---------------------------------------------------------------------------- -SUBROUTINE ExportMeshNodeInfo(obj, hdf5, dsetname) +SUBROUTINE ExportMeshNodeInfo(obj, hdf5, dSetname) CLASS(MSHFile_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 - TYPE(String), INTENT(IN) :: dsetname - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/tNodes", & + TYPE(String), INTENT(IN) :: dSetname + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/tNodes", & & vals=obj%Nodes%getNumNodes()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/tEntitiesForNodes", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/tEntitiesForNodes", & & vals=obj%Nodes%getnumEntityBlocks()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/minNptrs", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/minNptrs", & & vals=obj%Nodes%getMinNodeTag()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/maxNptrs", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/maxNptrs", & & vals=obj%Nodes%getMaxNodeTag()) END SUBROUTINE ExportMeshNodeInfo @@ -214,17 +214,17 @@ END SUBROUTINE ExportMeshNodeInfo ! ExportMeshElementInfo !---------------------------------------------------------------------------- -SUBROUTINE ExportMeshElementInfo(obj, hdf5, dsetname) +SUBROUTINE ExportMeshElementInfo(obj, hdf5, dSetname) CLASS(MSHFile_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 - TYPE(String), INTENT(IN) :: dsetname - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/tElements", & + TYPE(String), INTENT(IN) :: dSetname + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/tElements", & & vals=obj%Elements%getNumElements()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/tEntitiesForElements", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/tEntitiesForElements", & & vals=obj%Elements%getnumEntityBlocks()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/minElemNum", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/minElemNum", & & vals=obj%Elements%getMinElementTag()) - CALL hdf5%WRITE(dsetname=dsetname%chars()//"/maxElemNum", & + CALL hdf5%WRITE(dSetname=dSetname%chars()//"/maxElemNum", & & vals=obj%Elements%getMaxElementTag()) END SUBROUTINE ExportMeshElementInfo @@ -232,39 +232,39 @@ END SUBROUTINE ExportMeshElementInfo ! ExportMeshEntity !---------------------------------------------------------------------------- -SUBROUTINE ExportMeshEntity(obj, hdf5, dsetname, nsd) +SUBROUTINE ExportMeshEntity(obj, hdf5, dSetname, nsd) TYPE(mshEntity_), INTENT(IN) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 - CHARACTER(*), INTENT(IN) :: dsetname + CHARACTER(*), INTENT(IN) :: dSetname INTEGER(I4B), INTENT(IN) :: nsd INTEGER(I4B), ALLOCATABLE :: intvec(:) REAL(DFP), ALLOCATABLE :: realvec(:), realMat(:, :) - CALL hdf5%WRITE(TRIM(dsetname)//"/uid", obj%getUid()) - CALL hdf5%WRITE(TRIM(dsetname)//"/xidim", obj%getXidim()) - CALL hdf5%WRITE(TRIM(dsetname)//"/elemType", obj%getElemType()) - CALL hdf5%WRITE(TRIM(dsetname)//"/nsd", nsd) - CALL hdf5%WRITE(TRIM(dsetname)//"/minX", obj%getMinX()) - CALL hdf5%WRITE(TRIM(dsetname)//"/minY", obj%getMinY()) - CALL hdf5%WRITE(TRIM(dsetname)//"/minZ", obj%getMinZ()) - CALL hdf5%WRITE(TRIM(dsetname)//"/maxX", obj%getMaxX()) - CALL hdf5%WRITE(TRIM(dsetname)//"/maxY", obj%getMaxY()) - CALL hdf5%WRITE(TRIM(dsetname)//"/maxZ", obj%getMaxZ()) - CALL hdf5%WRITE(TRIM(dsetname)//"/x", obj%getX()) - CALL hdf5%WRITE(TRIM(dsetname)//"/y", obj%getY()) - CALL hdf5%WRITE(TRIM(dsetname)//"/z", obj%getZ()) - - CALL hdf5%WRITE(TRIM(dsetname)//"/tElements", obj%getTotalElements()) - CALL hdf5%WRITE(TRIM(dsetname)//"/tIntNodes", obj%getTotalIntNodes()) - - CALL hdf5%WRITE(TRIM(dsetname)//"/physicalTag", obj%getPhysicalTag()) - CALL hdf5%WRITE(TRIM(dsetname)//"/intNodeNumber", obj%getIntNodeNumber()) - CALL hdf5%WRITE(TRIM(dsetname)//"/elemNumber", obj%getElemNumber()) - CALL hdf5%WRITE(TRIM(dsetname)//"/connectivity", obj%getConnectivity()) + CALL hdf5%WRITE(TRIM(dSetname)//"/uid", obj%getUid()) + CALL hdf5%WRITE(TRIM(dSetname)//"/xidim", obj%getXidim()) + CALL hdf5%WRITE(TRIM(dSetname)//"/elemType", obj%getElemType()) + CALL hdf5%WRITE(TRIM(dSetname)//"/nsd", nsd) + CALL hdf5%WRITE(TRIM(dSetname)//"/minX", obj%getMinX()) + CALL hdf5%WRITE(TRIM(dSetname)//"/minY", obj%getMinY()) + CALL hdf5%WRITE(TRIM(dSetname)//"/minZ", obj%getMinZ()) + CALL hdf5%WRITE(TRIM(dSetname)//"/maxX", obj%getMaxX()) + CALL hdf5%WRITE(TRIM(dSetname)//"/maxY", obj%getMaxY()) + CALL hdf5%WRITE(TRIM(dSetname)//"/maxZ", obj%getMaxZ()) + CALL hdf5%WRITE(TRIM(dSetname)//"/x", obj%getX()) + CALL hdf5%WRITE(TRIM(dSetname)//"/y", obj%getY()) + CALL hdf5%WRITE(TRIM(dSetname)//"/z", obj%getZ()) + + CALL hdf5%WRITE(TRIM(dSetname)//"/tElements", obj%getTotalElements()) + CALL hdf5%WRITE(TRIM(dSetname)//"/tIntNodes", obj%getTotalIntNodes()) + + CALL hdf5%WRITE(TRIM(dSetname)//"/physicalTag", obj%getPhysicalTag()) + CALL hdf5%WRITE(TRIM(dSetname)//"/intNodeNumber", obj%getIntNodeNumber()) + CALL hdf5%WRITE(TRIM(dSetname)//"/elemNumber", obj%getElemNumber()) + CALL hdf5%WRITE(TRIM(dSetname)//"/connectivity", obj%getConnectivity()) intvec = obj%getBoundingEntity() IF (SIZE(intvec) .NE. 0) THEN - CALL hdf5%WRITE(TRIM(dsetname)//"/boundingEntity", & + CALL hdf5%WRITE(TRIM(dSetname)//"/boundingEntity", & & intvec) END IF END SUBROUTINE ExportMeshEntity @@ -280,17 +280,17 @@ SUBROUTINE getNodeCoord(obj, nodeCoord, local_nptrs, count_) INTEGER(I4B), INTENT(INOUT) :: count_ ! internal data REAL(DFP), ALLOCATABLE :: myNodeCoord(:, :) - INTEGER(I4B), ALLOCATABLE :: myNptrs(:) + INTEGER(I4B), ALLOCATABLE :: mynptrs(:) INTEGER(I4B) :: ii myNodeCoord = obj%getNodeCoord() - myNptrs = obj%getIntNodeNumber() - DO ii = 1, SIZE(myNptrs) + mynptrs = obj%getIntNodeNumber() + DO ii = 1, SIZE(mynptrs) count_ = count_ + 1 - local_nptrs(myNptrs(ii)) = count_ + local_nptrs(mynptrs(ii)) = count_ nodeCoord(:, count_) = myNodeCoord(:, ii) END DO IF (ALLOCATED(myNodeCoord)) DEALLOCATE (myNodeCoord) - IF (ALLOCATED(myNptrs)) DEALLOCATE (myNptrs) + IF (ALLOCATED(mynptrs)) DEALLOCATE (mynptrs) END SUBROUTINE getNodeCoord !---------------------------------------------------------------------------- @@ -301,73 +301,103 @@ END SUBROUTINE getNodeCoord ! Define internal variables CHARACTER(*), PARAMETER :: myName = "msh_Read" INTEGER(I4B) :: unitNo, tp, tc, ts, tv, error0 -!> main -!> check + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] msh_Read()') +#endif + IF (.NOT. obj%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'MSH File is not open, please open it first.') END IF -!> check + +! check IF (.NOT. obj%isRead()) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'MSH File does not have read permission.') END IF -!> +! unitNo = obj%getunitNo() -!> reading mesh format -CALL e%raiseDebug(modName//'::'//myName//' - '// & - & 'READING: meshFormat') + CALL obj%FORMAT%READ(mshFile=obj, error=error0) + IF (error0 .NE. 0) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Failed in Reading mesh format') -ELSE - CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: meshFormat [OK!]') + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Failed in Reading mesh format') END IF -!> reading physical group information -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: physicalNames') + +! reading physical group information CALL obj%PhysicalNames%READ(mshFile=obj, error=error0) + +#ifdef DEBUG_VER IF (obj%PhysicalNames%isInitiated) THEN - CALL e%raiseInformation(modName//'::'//myName//' - '// & + CALL e%RaiseInformation(modName//'::'//myName//' - '// & & 'READING: physicalNames [OK!]') ELSE - CALL e%raiseInformation(modName//'::'//myName//' - '// & + CALL e%RaiseInformation(modName//'::'//myName//' - '// & & 'READING: physicalNames [NOT FOUND!]') END IF -!> Entities -CALL e%raiseInformation(modName//'::'//myName//' - '// & +#endif + +! Entities + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & & 'LOCATING: $Entities') +#endif + CALL TypemshEntity%GotoTag(mshFile=obj, error=error0) + IF (error0 .NE. 0) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'LOCATING: $Entities [NOT FOUND!]') -ELSE - CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'LOCATING: $Entities [OK!]') END IF -!> Entities -CALL e%raiseInformation(modName//'::'//myName//' - '// & + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'LOCATING: $Entities [OK!]') + +CALL e%RaiseInformation(modName//'::'//myName//' - '// & & 'READING: $Entities') +#endif + READ (unitNo, *) tp, tc, ts, tv IF (tp .NE. 0) obj%nsd = 0 IF (tc .NE. 0) obj%nsd = 1 IF (ts .NE. 0) obj%nsd = 2 IF (tv .NE. 0) obj%nsd = 3 -CALL obj%ReadPointEntities(te=tp) -CALL obj%ReadCurveEntities(te=tc) -CALL obj%ReadSurfaceEntities(te=ts) -CALL obj%ReadVolumeEntities(te=tv) -CALL e%raiseInformation(modName//'::'//myName//' - '// & +IF (tp .NE. 0) THEN + CALL obj%ReadPointEntities(te=tp) +END IF +IF (tc .NE. 0) THEN + CALL obj%ReadCurveEntities(te=tc) +END IF +IF (ts .NE. 0) THEN + CALL obj%ReadSurfaceEntities(te=ts) +END IF +IF (tv .NE. 0) THEN + CALL obj%ReadVolumeEntities(te=tv) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & & 'READING: $Entities [OK!]') +#endif + !> Nodes CALL obj%ReadNodes() !> Elements + CALL obj%ReadElements() !> nodes in physical regions -CALL setNumNodesInPhysicalNames(obj) +CALL SetNumNodesInPhysicalNames(obj) IF (PRESENT(error)) error = error0 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] msh_Read()') +#endif END PROCEDURE msh_Read !---------------------------------------------------------------------------- @@ -375,18 +405,26 @@ END SUBROUTINE getNodeCoord !---------------------------------------------------------------------------- MODULE PROCEDURE msh_ReadPointEntities -INTEGER(I4B) :: unitNo -CHARACTER(*), PARAMETER :: myName = "ReadPointEntities" +CHARACTER(*), PARAMETER :: myName = "msh_ReadPointEntities" INTEGER(I4B) :: i, j, k, tpt, error, dim INTEGER(I4B), ALLOCATABLE :: PhysicalTag0(:) !> main program -dim = 0; unitNo = obj%getUnitNo() -CALL e%raiseInformation(modName//'::'//myName//' - ' & + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadPointEntities()') +#endif + +dim = 0 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - ' & & //'Total Point Entities: '//TRIM(str(te, .TRUE.))) +#endif + IF (ALLOCATED(obj%PointEntities)) DEALLOCATE (obj%PointEntities) IF (te .NE. 0) ALLOCATE (obj%PointEntities(te)) -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: PointEntities') + DO i = 1, te CALL obj%PointEntities(i)%READ(mshFile=obj, dim=dim, & & readTag=.FALSE., error=error) @@ -403,8 +441,12 @@ END SUBROUTINE getNodeCoord END DO END IF END DO -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: pointEntities [OK!]') + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadpointEntities') +#endif + END PROCEDURE msh_ReadPointEntities !---------------------------------------------------------------------------- @@ -412,18 +454,24 @@ END SUBROUTINE getNodeCoord !---------------------------------------------------------------------------- MODULE PROCEDURE msh_ReadCurveEntities -INTEGER(I4B) :: unitNo -CHARACTER(*), PARAMETER :: myName = "ReadCurveEntities" +CHARACTER(*), PARAMETER :: myName = "msh_ReadCurveEntities()" INTEGER(I4B) :: i, j, k, tpt, error, dim INTEGER(I4B), ALLOCATABLE :: PhysicalTag0(:) !> main program -dim = 1; unitNo = obj%getUnitNo() -CALL e%raiseInformation(modName//'::'//myName//' - ' & +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadCurveEntities()') +#endif +dim = 1 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - ' & & //'Total Curve Entities: '//TRIM(str(te, .TRUE.))) +#endif + IF (ALLOCATED(obj%CurveEntities)) DEALLOCATE (obj%CurveEntities) IF (te .NE. 0) ALLOCATE (obj%CurveEntities(te)) -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: CurveEntities') + DO i = 1, te CALL obj%CurveEntities(i)%READ(mshFile=obj, dim=dim, & & readTag=.FALSE., error=error) @@ -440,8 +488,9 @@ END SUBROUTINE getNodeCoord END DO END IF END DO -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: CurveEntities [OK!]') + +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadCurveEntities()') END PROCEDURE msh_ReadCurveEntities !---------------------------------------------------------------------------- @@ -449,18 +498,26 @@ END SUBROUTINE getNodeCoord !---------------------------------------------------------------------------- MODULE PROCEDURE msh_ReadSurfaceEntities -INTEGER(I4B) :: unitNo -CHARACTER(*), PARAMETER :: myName = "ReadSurfaceEntities" +CHARACTER(*), PARAMETER :: myName = "msh_ReadSurfaceEntities" INTEGER(I4B) :: i, j, k, tpt, error, dim INTEGER(I4B), ALLOCATABLE :: PhysicalTag0(:) !> main program -dim = 2; unitNo = obj%getUnitNo() -CALL e%raiseInformation(modName//'::'//myName//' - ' & + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START]: ReadSurfaceEntities()') +#endif + +dim = 2 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - ' & & //'Total Surface Entities: '//TRIM(str(te, .TRUE.))) +#endif + IF (ALLOCATED(obj%SurfaceEntities)) DEALLOCATE (obj%SurfaceEntities) IF (te .NE. 0) ALLOCATE (obj%SurfaceEntities(te)) -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: SurfaceEntities') + DO i = 1, te CALL obj%SurfaceEntities(i)%READ(mshFile=obj, dim=dim, & & readTag=.FALSE., error=error) @@ -477,8 +534,11 @@ END SUBROUTINE getNodeCoord END DO END IF END DO -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: SurfaceEntities [OK!]') + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END]: ReadSurfaceEntities()') +#endif END PROCEDURE msh_ReadSurfaceEntities !---------------------------------------------------------------------------- @@ -486,18 +546,26 @@ END SUBROUTINE getNodeCoord !---------------------------------------------------------------------------- MODULE PROCEDURE msh_ReadVolumeEntities -INTEGER(I4B) :: unitNo CHARACTER(*), PARAMETER :: myName = "ReadVolumeEntities" INTEGER(I4B) :: i, j, k, tpt, error, dim INTEGER(I4B), ALLOCATABLE :: PhysicalTag0(:) -!> main program -dim = 3; unitNo = obj%getUnitNo() -CALL e%raiseInformation(modName//'::'//myName//' - ' & +! main program + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadVolumeEntities()') +#endif + +dim = 3 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - ' & & //'Total Volume Entities: '//TRIM(str(te, .TRUE.))) +#endif + IF (ALLOCATED(obj%VolumeEntities)) DEALLOCATE (obj%VolumeEntities) IF (te .NE. 0) ALLOCATE (obj%VolumeEntities(te)) -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: VolumeEntities') + DO i = 1, te CALL obj%VolumeEntities(i)%READ(mshFile=obj, dim=dim, & & readTag=.FALSE., error=error) @@ -514,8 +582,11 @@ END SUBROUTINE getNodeCoord END DO END IF END DO -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: VolumeEntities [OK!]') + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadVolumeEntities()') +#endif END PROCEDURE msh_ReadVolumeEntities !---------------------------------------------------------------------------- @@ -526,53 +597,99 @@ END SUBROUTINE getNodeCoord !> internal variables CHARACTER(*), PARAMETER :: myName = "ReadNodes" INTEGER(I4B) :: i, j, k, l, entityDim, entityTag, parametric, & - & numNodesInBlock, error, unitNo + & numNodesInBlock, error INTEGER(I4B), ALLOCATABLE :: NodeNumber(:) REAL(DFP), ALLOCATABLE :: NodeCoord(:, :) -!> main program +! main program + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadNodes()') +#endif + ! we read first line of $Nodes block CALL obj%Nodes%READ(mshFile=obj, mshFormat=obj%FORMAT, & & error=error) -IF (error .NE. 0) & - & CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Error has occured in reading the header of nodes.') -unitNo = obj%getUnitNo() + +IF (error .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error has occured in reading '// & + & 'the header of nodes.') +END IF + !start reading each entity block DO i = 1, obj%Nodes%getnumEntityBlocks() + ! read entity dimension and entity tag (uid) - READ (UnitNo, *) entityDim, entityTag, parametric, numNodesInBlock + READ (obj%GetUnitNo(), *) entityDim, entityTag, parametric, numNodesInBlock CALL Reallocate(NodeNumber, numNodesInBlock) + ! now we read node numbers in NodeNumber( : ) - DO k = 1, numNodesInBlock; READ (UnitNo, *) NodeNumber(k); END DO + DO k = 1, numNodesInBlock + READ (obj%GetUnitNo(), *) NodeNumber(k) + END DO CALL Reallocate(NodeCoord, [3, numNodesInBlock]) + ! now we read node coordinates DO k = 1, numNodesInBlock - READ (UnitNo, *) (NodeCoord(l, k), l=1, 3) + READ (obj%GetUnitNo(), *) (NodeCoord(l, k), l=1, 3) END DO + !make case based on entity dimension SELECT CASE (entityDim) CASE (0) j = getIndex(obj%PointEntities, entityTag) - CALL obj%PointEntities(j)%setIntNodeNumber(NodeNumber) - CALL obj%PointEntities(j)%setNodeCoord(NodeCoord) + + IF (j .LE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: error in getting index of surfaceEntities') + END IF + + CALL obj%PointEntities(j)%SetIntNodeNumber(NodeNumber) + CALL obj%PointEntities(j)%SetNodeCoord(NodeCoord) + CASE (1) j = getIndex(obj%CurveEntities, entityTag) - CALL obj%CurveEntities(j)%setIntNodeNumber(NodeNumber) - CALL obj%CurveEntities(j)%setNodeCoord(NodeCoord) + + IF (j .LE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: error in getting index of surfaceEntities') + END IF + + CALL obj%CurveEntities(j)%SetIntNodeNumber(NodeNumber) + CALL obj%CurveEntities(j)%SetNodeCoord(NodeCoord) CASE (2) j = getIndex(obj%SurfaceEntities, entityTag) - CALL obj%SurfaceEntities(j)%setIntNodeNumber(NodeNumber) - CALL obj%SurfaceEntities(j)%setNodeCoord(NodeCoord) + + IF (j .LE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: error in getting index of surfaceEntities') + END IF + + CALL obj%SurfaceEntities(j)%SetIntNodeNumber(NodeNumber) + CALL obj%SurfaceEntities(j)%SetNodeCoord(NodeCoord) CASE (3) j = getIndex(obj%VolumeEntities, entityTag) - CALL obj%VolumeEntities(j)%setIntNodeNumber(NodeNumber) - CALL obj%VolumeEntities(j)%setNodeCoord(NodeCoord) + + IF (j .LE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: error in getting index of surfaceEntities') + END IF + + CALL obj%VolumeEntities(j)%SetIntNodeNumber(NodeNumber) + CALL obj%VolumeEntities(j)%SetNodeCoord(NodeCoord) END SELECT + END DO -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: $Nodes [OK!]') + IF (ALLOCATED(NodeNumber)) DEALLOCATE (NodeNumber) IF (ALLOCATED(NodeCoord)) DEALLOCATE (NodeCoord) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadNodes()') +#endif + END PROCEDURE msh_ReadNodes !---------------------------------------------------------------------------- @@ -584,36 +701,41 @@ END SUBROUTINE getNodeCoord CHARACTER(*), PARAMETER :: myName = "msh_ReadElements" INTEGER(I4B) :: i, j, k, l, entityDim, entityTag, elemType, & & numElementsInBlock, tNodes, tpt, unitNo, error -INTEGER(I4B), ALLOCATABLE :: ElemNumber(:), Nptrs(:, :), PhyTag(:) +INTEGER(I4B), ALLOCATABLE :: ElemNumber(:), nptrs(:, :), PhyTag(:) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadElements()') +#endif + +unitNo = obj%getunitNo() -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: $Elements') -unitNo = obj%getUnitNo() CALL obj%Elements%READ(mshFile=obj, mshFormat=obj%FORMAT, & & error=error) + IF (error .NE. 0) & - & CALL e%raiseError(modName//'::'//myName//' - '// & + & CALL e%RaiseError(modName//'::'//myName//' - '// & & 'Error has occured in reading the header of elements.') ! start reading each entity block DO i = 1, obj%Elements%getnumEntityBlocks() ! read entity dimension and entity tag (uid) - READ (UnitNo, *) entityDim, entityTag, elemType, numElementsInBlock + READ (unitNo, *) entityDim, entityTag, elemType, numElementsInBlock ! get the total number of nodes in element tNodes = TotalNodesInElement(elemType) CALL Reallocate(ElemNumber, numElementsInBlock) - CALL Reallocate(Nptrs, [tNodes, numElementsInBlock]) - ! now we read ElemNumber and Nptrs + CALL Reallocate(nptrs, [tNodes, numElementsInBlock]) + ! now we read ElemNumber and nptrs DO k = 1, numElementsInBlock - READ (UnitNo, *) ElemNumber(k), (Nptrs(l, k), l=1, tNodes) + READ (unitNo, *) ElemNumber(k), (nptrs(l, k), l=1, tNodes) END DO ! make case based on entity dimension SELECT CASE (entityDim) CASE (0) j = getIndex(obj%PointEntities, entityTag) - ! set the element type - CALL obj%PointEntities(j)%setElemType(elemType) - CALL obj%PointEntities(j)%setElemNumber(ElemNumber) - CALL obj%PointEntities(j)%setConnectivity(Nptrs) + ! Set the element type + CALL obj%PointEntities(j)%SetElemType(elemType) + CALL obj%PointEntities(j)%SetElemNumber(ElemNumber) + CALL obj%PointEntities(j)%SetConnectivity(nptrs) ! counting nodes in each physical group tpt = obj%PointEntities(j)%getTotalPhysicalTags() IF (tpt .NE. 0) THEN @@ -626,10 +748,10 @@ END SUBROUTINE getNodeCoord END IF CASE (1) j = getIndex(obj%CurveEntities, entityTag) - ! set the element type - CALL obj%CurveEntities(j)%setElemType(ElemType) - CALL obj%CurveEntities(j)%setElemNumber(ElemNumber) - CALL obj%CurveEntities(j)%setConnectivity(Nptrs) + ! Set the element type + CALL obj%CurveEntities(j)%SetElemType(ElemType) + CALL obj%CurveEntities(j)%SetElemNumber(ElemNumber) + CALL obj%CurveEntities(j)%SetConnectivity(nptrs) ! counting nodes in each physical group tpt = obj%CurveEntities(j)%getTotalPhysicalTags() IF (tpt .NE. 0) THEN @@ -642,10 +764,10 @@ END SUBROUTINE getNodeCoord END IF CASE (2) j = getIndex(obj%SurfaceEntities, entityTag) - ! set the element type - CALL obj%SurfaceEntities(j)%setElemType(ElemType) - CALL obj%SurfaceEntities(j)%setElemNumber(ElemNumber) - CALL obj%SurfaceEntities(j)%setConnectivity(Nptrs) + ! Set the element type + CALL obj%SurfaceEntities(j)%SetElemType(ElemType) + CALL obj%SurfaceEntities(j)%SetElemNumber(ElemNumber) + CALL obj%SurfaceEntities(j)%SetConnectivity(nptrs) ! counting nodes in each physical group tpt = obj%SurfaceEntities(j)%getTotalPhysicalTags() IF (tpt .NE. 0) THEN @@ -658,10 +780,10 @@ END SUBROUTINE getNodeCoord END IF CASE (3) j = getIndex(obj%VolumeEntities, entityTag) - ! set the element type - CALL obj%VolumeEntities(j)%setElemType(ElemType) - CALL obj%VolumeEntities(j)%setElemNumber(ElemNumber) - CALL obj%VolumeEntities(j)%setConnectivity(Nptrs) + ! Set the element type + CALL obj%VolumeEntities(j)%SetElemType(ElemType) + CALL obj%VolumeEntities(j)%SetElemNumber(ElemNumber) + CALL obj%VolumeEntities(j)%SetConnectivity(nptrs) ! counting nodes in each physical group tpt = obj%VolumeEntities(j)%getTotalPhysicalTags() IF (tpt .NE. 0) THEN @@ -674,28 +796,35 @@ END SUBROUTINE getNodeCoord END IF END SELECT END DO -IF (ALLOCATED(Nptrs)) DEALLOCATE (Nptrs) +IF (ALLOCATED(nptrs)) DEALLOCATE (nptrs) IF (ALLOCATED(ElemNumber)) DEALLOCATE (ElemNumber) IF (ALLOCATED(PhyTag)) DEALLOCATE (PhyTag) -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: $Elements [OK!]') + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadElements()') +#endif END PROCEDURE msh_ReadElements !---------------------------------------------------------------------------- -! setNumNodes +! SetNumNodes !---------------------------------------------------------------------------- -SUBROUTINE setNumNodesInPhysicalNames(obj) +SUBROUTINE SetNumNodesInPhysicalNames(obj) CLASS(MSHFile_), INTENT(INOUT) :: obj ! Internal variables - CHARACTER(*), PARAMETER :: myName = "setNumNodesInPhysicalNames" + CHARACTER(*), PARAMETER :: myName = "SetNumNodesInPhysicalNames()" INTEGER(I4B) :: tpt, i, j, k, tElements, dim - INTEGER(I4B), ALLOCATABLE :: Indx(:), entIndx(:), Nptrs(:), & - & dummyNptrs(:) + INTEGER(I4B), ALLOCATABLE :: Indx(:), entIndx(:), nptrs(:), & + & dummynptrs(:) !> main - CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: Nodes in Physical entities') - ALLOCATE (Nptrs(obj%Nodes%getMaxNodeTag())) + +#ifdef DEBUG_VER + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] SetNumNodesInPhysicalNames()') +#endif + + ALLOCATE (nptrs(obj%Nodes%getMaxNodeTag())) ! Points dim = 0 tpt = obj%PhysicalNames%getTotalPhysicalEntities([dim]) @@ -709,6 +838,7 @@ SUBROUTINE setNumNodesInPhysicalNames(obj) & incr=SIZE(entIndx)) END DO END IF + ! Curve dim = 1 tpt = obj%PhysicalNames%getTotalPhysicalEntities([dim]) @@ -718,18 +848,21 @@ SUBROUTINE setNumNodesInPhysicalNames(obj) DO i = 1, tpt ! get Entities associated entIndx = obj%PhysicalNames%getEntities(Indx(i)) - Nptrs = 0_I4B + nptrs = 0_I4B DO j = 1, SIZE(entIndx) tElements = obj%CurveEntities(entIndx(j))%getTotalElements() DO k = 1, tElements - dummyNptrs = obj%CurveEntities(entIndx(j))%getConnectivity(k) - Nptrs(dummyNptrs) = dummyNptrs + dummynptrs = obj%CurveEntities(entIndx(j))%getConnectivity(k) + nptrs(dummynptrs) = dummynptrs END DO END DO + ! count the nonzero nptrs - CALL obj%PhysicalNames%setNumNodes(indx=Indx(i), numNode=COUNT(Nptrs .NE. 0)) + CALL obj%PhysicalNames%SetNumNodes(indx=Indx(i), & + & numNode=COUNT(nptrs .NE. 0)) END DO END IF + ! Surface dim = 2 tpt = obj%PhysicalNames%getTotalPhysicalEntities(dim=[dim]) @@ -739,18 +872,21 @@ SUBROUTINE setNumNodesInPhysicalNames(obj) DO i = 1, tpt ! get Entities associated entIndx = obj%PhysicalNames%getEntities(indx=Indx(i)) - Nptrs = 0_I4B + nptrs = 0_I4B DO j = 1, SIZE(entIndx) tElements = obj%SurfaceEntities(entIndx(j))%getTotalElements() DO k = 1, tElements - dummyNptrs = obj%SurfaceEntities(entIndx(j))%getConnectivity(k) - Nptrs(dummyNptrs) = dummyNptrs + dummynptrs = obj%SurfaceEntities(entIndx(j))%getConnectivity(k) + nptrs(dummynptrs) = dummynptrs END DO END DO + ! count the nonzero nptrs - CALL obj%PhysicalNames%setNumNodes(indx=Indx(i), numNode=COUNT(Nptrs .NE. 0)) + CALL obj%PhysicalNames%SetNumNodes(indx=Indx(i), & + & numNode=COUNT(nptrs .NE. 0)) END DO END IF + ! Volume dim = 3 tpt = obj%PhysicalNames%getTotalPhysicalEntities(dim=[dim]) @@ -760,27 +896,30 @@ SUBROUTINE setNumNodesInPhysicalNames(obj) DO i = 1, tpt ! get Entities associated entIndx = obj%PhysicalNames%getEntities(Indx(i)) - Nptrs = 0_I4B + nptrs = 0_I4B DO j = 1, SIZE(entIndx) tElements = obj%VolumeEntities(entIndx(j))%getTotalElements() DO k = 1, tElements - dummyNptrs = obj%VolumeEntities(entIndx(j))%getConnectivity(k) - Nptrs(dummyNptrs) = dummyNptrs + dummynptrs = obj%VolumeEntities(entIndx(j))%getConnectivity(k) + nptrs(dummynptrs) = dummynptrs END DO END DO ! count the nonzero nptrs - CALL obj%PhysicalNames%setNumNodes(indx=Indx(i), & - & numNode=COUNT(Nptrs .NE. 0)) + CALL obj%PhysicalNames%SetNumNodes(indx=Indx(i), & + & numNode=COUNT(nptrs .NE. 0)) END DO END IF - CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'READING: Nodes in Physical entities [OK!]') ! add deallocate stmt IF (ALLOCATED(Indx)) DEALLOCATE (Indx) IF (ALLOCATED(entIndx)) DEALLOCATE (entIndx) - IF (ALLOCATED(Nptrs)) DEALLOCATE (Nptrs) - IF (ALLOCATED(DummyNptrs)) DEALLOCATE (DummyNptrs) -END SUBROUTINE setNumNodesInPhysicalNames + IF (ALLOCATED(nptrs)) DEALLOCATE (nptrs) + IF (ALLOCATED(Dummynptrs)) DEALLOCATE (Dummynptrs) + +#ifdef DEBUG_VER + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] SetNumNodesInPhysicalNames()') +#endif +END SUBROUTINE SetNumNodesInPhysicalNames ! !---------------------------------------------------------------------------- ! ! Display @@ -790,8 +929,8 @@ END SUBROUTINE setNumNodesInPhysicalNames ! ! Define internal variable ! INTEGER( I4B ) :: I, j ! ! output unit -! IF( PRESENT( UnitNo ) ) THEN -! I = UnitNo +! IF( PRESENT( unitNo ) ) THEN +! I = unitNo ! ELSE ! I = stdout ! END IF @@ -800,16 +939,16 @@ END SUBROUTINE setNumNodesInPhysicalNames ! WRITE( I, "(A)" ) TRIM( Msg ) ! END IF ! ! Printiting the Gmsh Format -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! CALL Display( obj%Format, "Mesh Format = ", I ) ! ! Printing the PhysicalNames -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! CALL Display( obj%PhysicalNames, "Physical Names", I ) ! ! Printing the point entities ! IF( ALLOCATED( obj%PointEntities ) ) THEN -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! WRITE( I, "(A)" ) "Point Entities" ! DO j = 1, SIZE( obj%PointEntities ) @@ -820,7 +959,7 @@ END SUBROUTINE setNumNodesInPhysicalNames ! END IF ! ! Printing the Curve entities ! IF( ALLOCATED( obj%CurveEntities ) ) THEN -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! WRITE( I, "(A)" ) "Curve Entities" ! DO j = 1, SIZE( obj%CurveEntities ) ! CALL Display( & @@ -830,7 +969,7 @@ END SUBROUTINE setNumNodesInPhysicalNames ! END IF ! ! Printing the Surface entities ! IF ( ALLOCATED( obj%SurfaceEntities ) ) THEN -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! WRITE( I, "(A)" ) "Surface Entities" ! DO j = 1, SIZE( obj%SurfaceEntities ) ! CALL Display( & @@ -840,7 +979,7 @@ END SUBROUTINE setNumNodesInPhysicalNames ! END IF ! ! Printing the Volume entities ! IF( ALLOCATED( obj%VolumeEntities ) ) THEN -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! WRITE( I, "(A)" ) "Volume Entities" ! DO j = 1, SIZE( obj%VolumeEntities ) ! CALL Display( & @@ -849,10 +988,10 @@ END SUBROUTINE setNumNodesInPhysicalNames ! END DO ! END IF ! ! Printing nodes -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! CALL Display( obj%Nodes, "Nodes", I ) ! ! Printing elements -! CALL BlankLines( UnitNo = I, NOL = 1 ) +! CALL BlankLines( unitNo = I, NOL = 1 ) ! CALL Display( obj%Elements, "Elements", I ) ! END PROCEDURE msh_display @@ -867,12 +1006,12 @@ END SUBROUTINE setNumNodesInPhysicalNames INTEGER(I4B) :: ii IF (.NOT. afile%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'TxtFile_:: afile is not open.') END IF IF (.NOT. afile%isWrite()) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'TxtFile_:: afile does not have write permission.') END IF @@ -949,7 +1088,7 @@ END SUBROUTINE setNumNodesInPhysicalNames CALL obj%ExportElements(afile=afile) ! nodes in physical regions -! CALL setNumNodesInPhysicalNames(obj) +! CALL SetNumNodesInPhysicalNames(obj) ! IF (PRESENT(error)) error = error0 END PROCEDURE msh_Export_txtfile @@ -963,7 +1102,7 @@ END SUBROUTINE setNumNodesInPhysicalNames INTEGER(I4B) :: ii INTEGER(I4B) :: tp, tc, ts, tv -unitNo = afile%getUnitNo() +unitNo = afile%getunitNo() WRITE (unitNo, "(A)") "$Nodes" CALL obj%nodes%WRITE(afile=afile) @@ -1015,7 +1154,7 @@ END SUBROUTINE setNumNodesInPhysicalNames INTEGER(I4B) :: ii INTEGER(I4B) :: tp, tc, ts, tv -unitNo = afile%getUnitNo() +unitNo = afile%getunitNo() WRITE (unitNo, "(A)") "$Elements" CALL obj%elements%WRITE(afile=afile) diff --git a/src/submodules/MSHFile/src/mshElements_Class@Methods.F90 b/src/submodules/MSHFile/src/mshElements_Class@Methods.F90 index 2139b4ecd..989a98510 100644 --- a/src/submodules/MSHFile/src/mshElements_Class@Methods.F90 +++ b/src/submodules/MSHFile/src/mshElements_Class@Methods.F90 @@ -33,10 +33,11 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE el_Deallocate -SELECT TYPE (obj) -TYPE IS (mshElements_) - obj = TypemshElements -END SELECT +obj%numElements = 0 +obj%numEntityBlocks = 0 +obj%minElementTag = 0 +obj%maxElementTag = 0 +obj%isSparse = .FALSE. END PROCEDURE el_Deallocate !---------------------------------------------------------------------------- @@ -48,30 +49,61 @@ INTEGER(I4B) :: IOSTAT, Reopen, unitNo CHARACTER(100) :: Dummy CHARACTER(*), PARAMETER :: myName = "el_GotoTag" +LOGICAL(LGT) :: isNotOpen, isNotRead -IF (.NOT. mshFile%isOpen() .OR. .NOT. mshFile%isRead()) THEN +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GotoTag()') +#endif + +isNotOpen = .NOT. mshFile%isOpen() +isNotRead = .NOT. mshFile%isRead() + +IF (isNotOpen .OR. isNotRead) THEN CALL e%raiseError(modName//'::'//myName//' - '// & - & 'mshFile is either not opened or does not have read access!') + & '[INTERNAL ERROR] :: mshFile is either not opened '// & + & 'or does not have read access!') error = -1 -ELSE - Reopen = 0; error = 0; CALL mshFile%REWIND() - DO - unitNo = mshFile%getUnitNo() - READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy - IF (IS_IOSTAT_END(IOSTAT)) THEN - CALL mshFile%setEOFStat(.TRUE.) - Reopen = Reopen + 1 - END IF - IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Could not find $Elements !') - error = -2 - EXIT - ELSE IF (TRIM(Dummy) .EQ. '$Elements') THEN - EXIT - END IF - END DO + RETURN END IF + +Reopen = 0; error = 0 + +#ifndef Darwin_SYSTEM +CALL mshFile%REWIND() +#endif + +DO + + unitNo = mshFile%getUnitNo() + READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy + + IF (IS_IOSTAT_END(IOSTAT)) THEN + CALL mshFile%setEOFStat(.TRUE.) + +#ifdef Darwin_SYSTEM + CALL mshFile%CLOSE() + CALL mshFile%OPEN() +#endif + + Reopen = Reopen + 1 + END IF + + IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Could not find $Elements !') + error = -2 + EXIT + ELSE IF (TRIM(Dummy) .EQ. '$Elements') THEN + EXIT + END IF + +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GotoTag()') +#endif END PROCEDURE el_GotoTag !---------------------------------------------------------------------------- @@ -79,21 +111,37 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE el_Read +CHARACTER(*), PARAMETER :: myName = "el_Read()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] el_Read()') +#endif + CALL obj%GotoTag(mshFile, error) -IF (error .EQ. 0) THEN - IF (mshFormat%getMajorVersion() .GT. 2) THEN - READ (mshFile%getUnitNo(), *) obj%numEntityBlocks, obj%numElements, & - & obj%minElementTag, obj%maxElementTag - IF ((obj%maxElementTag - obj%minElementTag) & - & .EQ. (obj%numElements - 1)) THEN - obj%isSparse = .FALSE. - ELSE - obj%isSparse = .TRUE. - END IF +IF (error .NE. 0) THEN + CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[INTERNAL ERROR] :: some error occured while finding the tag.') +END IF + +IF (mshFormat%getMajorVersion() .GT. 2) THEN + READ (mshFile%getUnitNo(), *) obj%numEntityBlocks, obj%numElements, & + & obj%minElementTag, obj%maxElementTag + IF ((obj%maxElementTag - obj%minElementTag) & + & .EQ. (obj%numElements - 1)) THEN + obj%isSparse = .FALSE. ELSE - READ (mshFile%getUnitNo(), *) obj%numElements + obj%isSparse = .TRUE. END IF +ELSE + READ (mshFile%getUnitNo(), *) obj%numElements END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] el_Read()') +#endif + END PROCEDURE el_Read !---------------------------------------------------------------------------- diff --git a/src/submodules/MSHFile/src/mshEntity_Class@Methods.F90 b/src/submodules/MSHFile/src/mshEntity_Class@Methods.F90 index 7d3a9d36b..fcc12566c 100644 --- a/src/submodules/MSHFile/src/mshEntity_Class@Methods.F90 +++ b/src/submodules/MSHFile/src/mshEntity_Class@Methods.F90 @@ -62,34 +62,67 @@ INTEGER(I4B) :: IOSTAT, Reopen, unitNo CHARACTER(100) :: Dummy, IOMSG CHARACTER(*), PARAMETER :: myName = "ent_GotoTag" -! -! Find $meshFormat +LOGICAL(LGT) :: isNotOpen, isNotRead, isNotInit + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GotoTag()') +#endif - IF( .NOT. mshFile%isOpen() .OR. .NOT. mshFile%isRead() .OR. .NOT. mshFile%isInitiated() ) THEN +isNotOpen = .NOT. mshFile%isOpen() +isNotRead = .NOT. mshFile%isRead() +isNotInit = .NOT. mshFile%isInitiated() + +IF (isNotOpen .OR. isNotRead .OR. isNotInit) THEN CALL e%raiseError(modName//'::'//myName//' - '// & - & 'mshFile is either not opened or does not have read access!') + & '[INTERNAL ERROR] :: mshFile is either not opened or '// & + & 'does not have read access!') error = -1 -ELSE - Reopen = 0; error = 0; CALL mshFile%REWIND() - DO - unitNo = mshFile%getUnitNo(); Dummy = "" - READ (unitNo, "(A)", IOSTAT=IOSTAT, IOMSG=IOMSG) Dummy - IF (IS_IOSTAT_END(IOSTAT)) THEN - CALL mshFile%setEOFStat(.TRUE.) - Reopen = Reopen + 1 - END IF - IF (IOSTAT .GT. 0 .AND. Reopen .GT. 1) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Could not find $Entities !'//' :: Reopen='// & - & TOSTRING(Reopen)//' :: IOSTAT='//TOSTRING(IOSTAT) & - & //" :: IOMSG="//TRIM(IOMSG)) - error = -2 - EXIT - ELSE IF (TRIM(Dummy) .EQ. '$Entities') THEN - EXIT - END IF - END DO + RETURN END IF + +Reopen = 0; error = 0 + +#ifndef Darwin_SYSTEM +CALL mshFile%REWIND() +#endif + +DO + + unitNo = mshFile%getUnitNo(); Dummy = "" + READ (unitNo, "(A)", IOSTAT=IOSTAT, IOMSG=IOMSG) Dummy + + IF (IS_IOSTAT_END(IOSTAT)) THEN + CALL mshFile%setEOFStat(.TRUE.) + +#ifdef Darwin_SYSTEM + CALL mshFile%CLOSE() + CALL mshFile%OPEN() +#endif + + Reopen = Reopen + 1 + END IF + + IF (IOSTAT .GT. 0 .AND. Reopen .GT. 1) THEN + + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Could not find $Entities !'//' :: Reopen='// & + & TOSTRING(Reopen)//' :: IOSTAT='//TOSTRING(IOSTAT) & + & //" :: IOMSG="//TRIM(IOMSG)) + error = -2 + EXIT + + ELSE IF (TRIM(Dummy) .EQ. '$Entities') THEN + + EXIT + + END IF +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GotoTag()') +#endif END PROCEDURE ent_GotoTag !---------------------------------------------------------------------------- @@ -97,6 +130,13 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE ent_Write +CHARACTER(*), PARAMETER :: myName = "ent_Write()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Write()') +#endif + SELECT CASE (dim) CASE (0) CALL WritePointEntity(obj, afile) @@ -107,6 +147,11 @@ CASE (3) CALL WriteVolumeEntity(obj, afile) END SELECT + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Write()') +#endif END PROCEDURE ent_Write !---------------------------------------------------------------------------- @@ -432,6 +477,13 @@ END SUBROUTINE WriteVolumeEntity !---------------------------------------------------------------------------- MODULE PROCEDURE ent_Read +CHARACTER(*), PARAMETER :: myName = "ent_Read" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Read()') +#endif + SELECT CASE (dim) CASE (0) CALL ReadPointEntity(obj, mshFile, readTag, error) @@ -442,6 +494,11 @@ END SUBROUTINE WriteVolumeEntity CASE (3) CALL ReadVolumeEntity(obj, mshFile, readTag, error) END SELECT + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Read()') +#endif END PROCEDURE ent_Read !---------------------------------------------------------------------------- @@ -518,60 +575,114 @@ END SUBROUTINE WriteVolumeEntity INTEGER(I4B) :: n, i, m TYPE(String) :: aline TYPE(String), ALLOCATABLE :: entries(:) -! +CHARACTER(*), PARAMETER :: myName = "ReadSurfaceEntity()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadSurfaceEntity()') +#endif + IF (ReadTag) THEN CALL obj%GotoTag(mshFile, error) ELSE error = 0 END IF -IF (error .EQ. 0) THEN - obj%XiDim = 2 - CALL aline%read_line(unit=mshFile%getUnitno()) - CALL aline%split(tokens=entries, sep=' ') - obj%Uid = entries(1)%to_number(kind=1_I4B) +IF (error .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Some error occured while finding tag') +END IF + +obj%XiDim = 2 +! CALL aline%read_line(unit=mshFile%getUnitno()) +CALL mshFile%ReadLine(val=aline, iostat=error) - obj%minX = entries(2)%to_number(kind=1.0_DFP) - obj%minY = entries(3)%to_number(kind=1.0_DFP) - obj%minZ = entries(4)%to_number(kind=1.0_DFP) +IF (error .GT. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error occured in reading the line '// & + & ' error = '//tostring(error)) +END IF - obj%maxX = entries(5)%to_number(kind=1.0_DFP) - obj%maxY = entries(6)%to_number(kind=1.0_DFP) - obj%maxZ = entries(7)%to_number(kind=1.0_DFP) +CALL aline%split(tokens=entries, sep=' ') - n = entries(8)%to_number(kind=I4B) - IF (n .NE. 0) THEN - ALLOCATE (IntVec1(n)) - DO i = 1, n - IntVec1(i) = entries(8 + i)%to_number(kind=I4B) - END DO - END IF - !! check total length here - m = entries(9 + n)%to_number(kind=I4B) - IF (m .NE. 0) THEN - ALLOCATE (IntVec2(m)) - DO i = 1, m - IntVec2(i) = entries(9 + n + i)%to_number(kind=I4B) - END DO +IF (ALLOCATED(entries)) THEN + IF (SIZE(entries) .LT. 8) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR 1] :: Error reading surface entities!') + error = -1 + RETURN END IF +END IF - IF (ALLOCATED(obj%physicalTag)) DEALLOCATE (obj%physicalTag) - IF (ALLOCATED(obj%BoundingEntity)) DEALLOCATE (obj%BoundingEntity) +obj%uid = entries(1)%to_number(kind=1_I4B) - IF (n .NE. 0) THEN - ALLOCATE (obj%physicalTag(n)) - obj%physicalTag(1:n) = Intvec1(1:n) +obj%minX = entries(2)%to_number(kind=1.0_DFP) +obj%minY = entries(3)%to_number(kind=1.0_DFP) +obj%minZ = entries(4)%to_number(kind=1.0_DFP) + +obj%maxX = entries(5)%to_number(kind=1.0_DFP) +obj%maxY = entries(6)%to_number(kind=1.0_DFP) +obj%maxZ = entries(7)%to_number(kind=1.0_DFP) + +n = 0 +n = entries(8)%to_number(kind=I4B) + +IF (ALLOCATED(entries)) THEN + IF (SIZE(entries) .LT. 8 + n) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR 2] :: Error reading surface entities!') + error = -2 + RETURN END IF +END IF - IF (m .NE. 0) THEN - ALLOCATE (obj%BoundingEntity(m)) - obj%BoundingEntity(1:m) = Intvec2(1:m) +IF (n .NE. 0) THEN + ALLOCATE (IntVec1(n)) + DO i = 1, n + IntVec1(i) = entries(8 + i)%to_number(kind=I4B) + END DO +END IF + + !! check total length here +m = entries(9 + n)%to_number(kind=I4B) + +IF (ALLOCATED(entries)) THEN + IF (SIZE(entries) .LT. 9 + n + m) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR 3] :: Error reading surface entities!') + error = -3 + RETURN END IF END IF +IF (m .NE. 0) THEN + ALLOCATE (IntVec2(m)) + DO i = 1, m + IntVec2(i) = entries(9 + n + i)%to_number(kind=I4B) + END DO +END IF + +IF (ALLOCATED(obj%physicalTag)) DEALLOCATE (obj%physicalTag) +IF (ALLOCATED(obj%BoundingEntity)) DEALLOCATE (obj%BoundingEntity) + +IF (n .NE. 0) THEN + ALLOCATE (obj%physicalTag(n)) + obj%physicalTag(1:n) = Intvec1(1:n) +END IF + +IF (m .NE. 0) THEN + ALLOCATE (obj%BoundingEntity(m)) + obj%BoundingEntity(1:m) = Intvec2(1:m) +END IF + IF (ALLOCATED(IntVec1)) DEALLOCATE (IntVec1) IF (ALLOCATED(IntVec2)) DEALLOCATE (IntVec2) IF (ALLOCATED(entries)) DEALLOCATE (entries) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadSurfaceEntity()') +#endif END PROCEDURE ReadSurfaceEntity !---------------------------------------------------------------------------- @@ -584,62 +695,111 @@ END SUBROUTINE WriteVolumeEntity INTEGER(I4B) :: n, i, m TYPE(String) :: aline TYPE(String), ALLOCATABLE :: entries(:) +CHARACTER(*), PARAMETER :: myName = "ReadVolumeEntity()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ReadVolumeEntity()') +#endif IF (ReadTag) THEN CALL obj%GotoTag(mshFile, error) ELSE error = 0 END IF -! -IF (error .EQ. 0) THEN - obj%XiDim = 3 - CALL aline%read_line(unit=mshFile%getUnitno()) - CALL aline%split(tokens=entries, sep=' ') - obj%Uid = entries(1)%to_number(kind=I4B) +IF (error .NE. 0) THEN + RETURN +END IF - obj%minX = entries(2)%to_number(kind=1.0_DFP) - obj%minY = entries(3)%to_number(kind=1.0_DFP) - obj%minZ = entries(4)%to_number(kind=1.0_DFP) +obj%XiDim = 3 - obj%maxX = entries(5)%to_number(kind=1.0_DFP) - obj%maxY = entries(6)%to_number(kind=1.0_DFP) - obj%maxZ = entries(7)%to_number(kind=1.0_DFP) +CALL mshFile%readLine(val=aline, iostat=error) - n = entries(8)%to_number(kind=I4B) - IF (n .NE. 0) THEN - ALLOCATE (IntVec1(n)) - DO i = 1, n - IntVec1(i) = entries(8 + i)%to_number(kind=I4B) - END DO - END IF - !! check total length here - m = entries(9 + n)%to_number(kind=I4B) - IF (m .NE. 0) THEN - ALLOCATE (IntVec2(m)) - DO i = 1, m - IntVec2(i) = entries(9 + n + i)%to_number(kind=I4B) - END DO +IF (error .GT. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: error in reading a line.') +END IF + +CALL aline%split(tokens=entries, sep=' ') + +IF (ALLOCATED(entries)) THEN + IF (SIZE(entries) .LT. 8) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR 1] :: Error reading volume entities!') + error = -1 + RETURN END IF +END IF - IF (ALLOCATED(obj%physicalTag)) DEALLOCATE (obj%physicalTag) - IF (ALLOCATED(obj%BoundingEntity)) DEALLOCATE (obj%BoundingEntity) - ! - IF (n .NE. 0) THEN - ALLOCATE (obj%physicalTag(n)) - obj%physicalTag(1:n) = Intvec1(1:n) +obj%Uid = entries(1)%to_number(kind=I4B) + +obj%minX = entries(2)%to_number(kind=1.0_DFP) +obj%minY = entries(3)%to_number(kind=1.0_DFP) +obj%minZ = entries(4)%to_number(kind=1.0_DFP) + +obj%maxX = entries(5)%to_number(kind=1.0_DFP) +obj%maxY = entries(6)%to_number(kind=1.0_DFP) +obj%maxZ = entries(7)%to_number(kind=1.0_DFP) + +n = 0 +n = entries(8)%to_number(kind=I4B) + +IF (ALLOCATED(entries)) THEN + IF (SIZE(entries) .LT. 8 + n) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR 2] :: Error reading volume entities!') + error = -2 + RETURN END IF - ! - IF (m .NE. 0) THEN - ALLOCATE (obj%BoundingEntity(m)) - obj%BoundingEntity(1:m) = Intvec2(1:m) +END IF + +IF (n .NE. 0) THEN + ALLOCATE (IntVec1(n)) + DO i = 1, n + IntVec1(i) = entries(8 + i)%to_number(kind=I4B) + END DO +END IF + !! check total length here +m = entries(9 + n)%to_number(kind=I4B) + +IF (ALLOCATED(entries)) THEN + IF (SIZE(entries) .LT. 9 + n + m) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR 3] :: Error reading volume entities!') + error = -3 + RETURN END IF END IF +IF (m .NE. 0) THEN + ALLOCATE (IntVec2(m)) + DO i = 1, m + IntVec2(i) = entries(9 + n + i)%to_number(kind=I4B) + END DO +END IF + +IF (ALLOCATED(obj%physicalTag)) DEALLOCATE (obj%physicalTag) +IF (ALLOCATED(obj%BoundingEntity)) DEALLOCATE (obj%BoundingEntity) + +IF (n .NE. 0) THEN + ALLOCATE (obj%physicalTag(n)) + obj%physicalTag(1:n) = Intvec1(1:n) +END IF + +IF (m .NE. 0) THEN + ALLOCATE (obj%BoundingEntity(m)) + obj%BoundingEntity(1:m) = Intvec2(1:m) +END IF + IF (ALLOCATED(IntVec1)) DEALLOCATE (IntVec1) IF (ALLOCATED(IntVec2)) DEALLOCATE (IntVec2) IF (ALLOCATED(entries)) DEALLOCATE (Entries) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ReadVolumeEntity()') +#endif END PROCEDURE ReadVolumeEntity !---------------------------------------------------------------------------- @@ -652,7 +812,7 @@ END SUBROUTINE WriteVolumeEntity ans = 0 tSize = SIZE(mshEntities) DO j = 1, tSize - IF (mshEntities(j)%UiD .EQ. UiD) THEN + IF (mshEntities(j)%UiD .EQ. uid) THEN ans = j EXIT END IF diff --git a/src/submodules/MSHFile/src/mshFormat_Class@Methods.F90 b/src/submodules/MSHFile/src/mshFormat_Class@Methods.F90 index ce91b424c..10ab92609 100644 --- a/src/submodules/MSHFile/src/mshFormat_Class@Methods.F90 +++ b/src/submodules/MSHFile/src/mshFormat_Class@Methods.F90 @@ -114,7 +114,7 @@ ELSE CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Could not read mesh format from mshFile !') + & '[INTERNAL ERROR] :: Could not read mesh format from mshFile !') END IF END PROCEDURE fmt_Read @@ -163,25 +163,49 @@ INTEGER(I4B) :: IOSTAT, Reopen, unitNo CHARACTER(100) :: Dummy CHARACTER(*), PARAMETER :: myName = "fmt_GotoTag" -! +LOGICAL(LGT) :: isNotOpen, isNotRead ! Find $meshFormat -IF (.NOT. mshFile%isOpen() .OR. .NOT. mshFile%isRead()) THEN +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GotoTag()') +#endif + +isNotOpen = .NOT. mshFile%isOpen() +isNotRead = .NOT. mshFile%isRead() + +IF (isNotOpen .OR. isNotRead) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & - & 'mshFile is either not opened or does not have read access!') + & '[INTERNAL ERROR] :: mshFile is either not opened or '// & + & 'does not have read access!') error = -1 + ELSE - Reopen = 0; error = 0; CALL mshFile%REWIND() + + Reopen = 0 + error = 0 + +#ifndef Darwin_SYSTEM + CALL mshFile%REWIND() +#endif + DO - unitNo = mshFile%getUnitNo() + unitNo = mshFile%GetUnitNo() READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy IF (IS_IOSTAT_END(IOSTAT)) THEN - CALL mshFile%setEOFStat(.TRUE.) + CALL mshFile%SetEOFStat(.TRUE.) + +#ifdef Darwin_SYSTEM + CALL mshFile%Close() + CALL mshFile%Open() +#endif + Reopen = Reopen + 1 END IF IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Could not find $MeshFormat!') + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Could not find $MeshFormat!') error = -2 EXIT ELSE IF (TRIM(Dummy) .EQ. '$MeshFormat') THEN @@ -189,6 +213,12 @@ END IF END DO END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GotoTag()') +#endif + END PROCEDURE fmt_GotoTag !---------------------------------------------------------------------------- diff --git a/src/submodules/MSHFile/src/mshNodes_Class@Methods.F90 b/src/submodules/MSHFile/src/mshNodes_Class@Methods.F90 index 36bdcb429..6c73c5659 100644 --- a/src/submodules/MSHFile/src/mshNodes_Class@Methods.F90 +++ b/src/submodules/MSHFile/src/mshNodes_Class@Methods.F90 @@ -34,10 +34,11 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE n_Deallocate -SELECT TYPE (obj) -TYPE IS (mshNodes_) - obj = TypeMSHNodes -END SELECT +obj%numNodes = 0 +obj%numEntityBlocks = 0 +obj%minNodeTag = 0 +obj%maxNodeTag = 0 +obj%isSparse = .FALSE. END PROCEDURE n_Deallocate !---------------------------------------------------------------------------- @@ -49,32 +50,59 @@ INTEGER(I4B) :: IOSTAT, Reopen, unitNo CHARACTER(100) :: Dummy CHARACTER(*), PARAMETER :: myName = "n_GotoTag" -! -! Find $meshFormat +LOGICAL(LGT) :: isNotOpen, isNotRead + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GotoTag()') +#endif -IF (.NOT. mshFile%isOpen() .OR. .NOT. mshFile%isRead()) THEN +isNotOpen = .NOT. mshFile%isOpen() +isNotRead = .NOT. mshFile%isRead() + +! Find $meshFormat +IF (isNotOpen .OR. isNotRead) THEN CALL e%raiseError(modName//'::'//myName//' - '// & - & 'mshFile is either not opened or does not have read access!') + & '[INTERNAL ERROR] :: mshFile is either not opened '// & + & 'or does not have read access!') error = -1 -ELSE - Reopen = 0; error = 0; CALL mshFile%REWIND() - DO - unitNo = mshFile%getUnitNo() - READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy - IF (IS_IOSTAT_END(IOSTAT)) THEN - CALL mshFile%setEOFStat(.TRUE.) - Reopen = Reopen + 1 - END IF - IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'Could not find $Nodes !') - error = -2 - EXIT - ELSE IF (TRIM(Dummy) .EQ. '$Nodes') THEN - EXIT - END IF - END DO + RETURN END IF + +Reopen = 0; error = 0; +#ifndef Darwin_SYSTEM +CALL mshFile%REWIND() +#endif + +DO + unitNo = mshFile%getUnitNo() + READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy + + IF (IS_IOSTAT_END(IOSTAT)) THEN + CALL mshFile%setEOFStat(.TRUE.) + +#ifdef Darwin_SYSTEM + CALL mshFile%CLOSE() + CALL mshFile%OPEN() +#endif + + Reopen = Reopen + 1 + END IF + + IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Could not find $Nodes !') + error = -2 + EXIT + ELSE IF (TRIM(Dummy) .EQ. '$Nodes') THEN + EXIT + END IF +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GotoTag()') +#endif END PROCEDURE n_GotoTag !---------------------------------------------------------------------------- @@ -82,21 +110,37 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE n_Read +CHARACTER(*), PARAMETER :: myName = "n_Read()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Read()') +#endif + CALL obj%GotoTag(mshFile, error) -IF (error .EQ. 0) THEN - IF (mshFormat%getMajorVersion() .GT. 2) THEN - READ (mshFile%getUnitNo(), *) obj%numEntityBlocks, obj%numNodes, & - & obj%minNodeTag, obj%maxNodeTag - IF ((obj%maxNodeTag - obj%minNodeTag) & - & .EQ. (obj%numNodes - 1)) THEN - obj%isSparse = .FALSE. - ELSE - obj%isSparse = .TRUE. - END IF + +IF (error .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error occured while finding the tag.') +END IF + +IF (mshFormat%getMajorVersion() .GT. 2) THEN + READ (mshFile%getUnitNo(), *) obj%numEntityBlocks, obj%numNodes, & + & obj%minNodeTag, obj%maxNodeTag + IF ((obj%maxNodeTag - obj%minNodeTag) & + & .EQ. (obj%numNodes - 1)) THEN + obj%isSparse = .FALSE. ELSE - READ (mshFile%getUnitNo(), *) obj%numNodes + obj%isSparse = .TRUE. END IF +ELSE + READ (mshFile%getUnitNo(), *) obj%numNodes END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Read()') +#endif END PROCEDURE n_Read !---------------------------------------------------------------------------- diff --git a/src/submodules/MSHFile/src/mshPhysicalNames_Class@Methods.F90 b/src/submodules/MSHFile/src/mshPhysicalNames_Class@Methods.F90 index edec06bdd..907455250 100644 --- a/src/submodules/MSHFile/src/mshPhysicalNames_Class@Methods.F90 +++ b/src/submodules/MSHFile/src/mshPhysicalNames_Class@Methods.F90 @@ -51,29 +51,60 @@ INTEGER(I4B) :: IOSTAT, Reopen, unitNo CHARACTER(100) :: Dummy CHARACTER(*), PARAMETER :: myName = "pn_GotoTag" -! +LOGICAL(LGT) :: isNotOpen, isNotRead + ! Find $PhysicalNames -IF (.NOT. mshFile%isOpen() .OR. .NOT. mshFile%isRead()) THEN + +#ifdef DEBUG_VER +CALL e%raiseInformation(modName//'::'//myName//' - '// & + & '[START] GotoTag()') +#endif + +isNotOpen = .NOT. mshFile%isOpen() +isNotRead = .NOT. mshFile%isRead() + +IF (isNotOpen .OR. isNotRead) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & - & 'mshFile is either not opened or does not have read access!') + & '[INTERNAL ERROR] :: mshFile is either not opened or does not have read access!') error = -1 -ELSE - Reopen = 0; error = 0; CALL mshFile%REWIND() - DO - unitNo = mshFile%getUnitNo() - READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy - IF (IS_IOSTAT_END(IOSTAT)) THEN - CALL mshFile%setEOFStat(.TRUE.) - Reopen = Reopen + 1 - END IF - IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN - error = -2 - EXIT - ELSE IF (TRIM(Dummy) .EQ. '$PhysicalNames') THEN - EXIT - END IF - END DO + RETURN + END IF + +Reopen = 0 +error = 0 + +#ifndef Darwin_SYSTEM + CALL mshFile%REWIND() +#endif + +DO + unitNo = mshFile%getUnitNo() + READ (unitNo, "(A)", IOSTAT=IOSTAT) Dummy + IF (IS_IOSTAT_END(IOSTAT)) THEN + CALL mshFile%setEOFStat(.TRUE.) + +#ifdef Darwin_SYSTEM + CALL mshFile%CLOSE() + CALL mshFile%OPEN() +#endif + + Reopen = Reopen + 1 + + END IF + IF (IOSTAT .GT. 0 .OR. Reopen .GT. 1) THEN + error = -2 + EXIT + ELSE IF (TRIM(Dummy) .EQ. '$PhysicalNames') THEN + EXIT + END IF +END DO + +#ifdef DEBUG_VER +CALL e%raiseInformation(modName//'::'//myName//' - '// & + & '[END] GotoTag()') +#endif END PROCEDURE pn_GotoTag !---------------------------------------------------------------------------- @@ -86,12 +117,17 @@ CHARACTER(maxStrLen) :: dummystr CHARACTER(*), PARAMETER :: myName = "pn_Read" +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName //'::'//myName// ' - '// & + & '[START] Read()') +#endif + ! Go to $PhysicalNames CALL obj%GotoTag(mshFile, error) + IF (error .EQ. 0) THEN - CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'PhysicalNames FOUND in the mshFile!') - CALL Obj%DEALLOCATE() + + CALL obj%DEALLOCATE() obj%isInitiated = .TRUE. unitNo = mshFile%getUnitNo() READ (UnitNo, *) tp @@ -112,9 +148,13 @@ END DO ELSE obj%isInitiated = .FALSE. - CALL e%raiseInformation(modName//'::'//myName//' - '// & - & 'PhysicalNames information is not present in the mshFile !') + CALL obj%DEALLOCATE() END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName //'::'//myName// ' - '// & + & '[END] Read()') +#endif END PROCEDURE pn_Read !---------------------------------------------------------------------------- diff --git a/src/submodules/Mesh/src/Mesh_Class@ShapeDataMethods.F90 b/src/submodules/Mesh/src/Mesh_Class@ShapeDataMethods.F90 index 6808fcbe2..c561d71b4 100644 --- a/src/submodules/Mesh/src/Mesh_Class@ShapeDataMethods.F90 +++ b/src/submodules/Mesh/src/Mesh_Class@ShapeDataMethods.F90 @@ -25,31 +25,30 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE mesh_initiateElemSD1 -! + ! main -! obj%quadTypeForSpace = TRIM(quadTypeForSpace) obj%continuityTypeForSpace = TRIM(continuityTypeForSpace) obj%interpolTypeForSpace = TRIM(interpolTypeForSpace) obj%orderSpace = orderSpace -! + CALL Initiate(obj=obj%quadForSpace, & & refelem=spaceElem, & & order=orderSpace, & & QuadratureType=quadTypeForSpace) -! + CALL Initiate(obj=obj%linSpaceElemSD, & & quad=obj%quadForSpace, & & refelem=linSpaceElem, & & ContinuityType=continuityTypeForSpace, & & InterpolType=interpolTypeForSpace) -! + CALL Initiate(obj=obj%spaceElemSD, & & quad=obj%quadForSpace, & & refelem=spaceElem, & & ContinuityType=continuityTypeForSpace, & & InterpolType=interpolTypeForSpace) -! + END PROCEDURE mesh_initiateElemSD1 !---------------------------------------------------------------------------- @@ -144,85 +143,84 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE mesh_initiateFacetElemSD1 -! +CHARACTER(*), PARAMETER :: myName = "mesh_initiateFacetElemSD1" INTEGER(I4B) :: nn, ii INTEGER(I4B), ALLOCATABLE :: faceNptrs(:) REAL(DFP), ALLOCATABLE :: xijCell(:, :), quadPointsCell(:, :), & & points(:, :) -CHARACTER(*), PARAMETER :: myName = "mesh_initiateFacetElemSD1" -! + IF (.NOT. ALLOCATED(obj%facetElements)) THEN CALL e%raiseError(modName//'::'//myName//' - '// & & 'In Mesh_ object facetElements are not allocated!') END IF -! + nn = SIZE(obj%facetElements) -! + IF (.NOT. ALLOCATED(obj%quadForFacet)) & & ALLOCATE (obj%quadForFacet(nn)) -! + IF (.NOT. ALLOCATED(obj%quadForFacetCell)) & & ALLOCATE (obj%quadForFacetCell(nn)) -! + IF (.NOT. ALLOCATED(obj%linFacetElemSD)) & & ALLOCATE (obj%linFacetElemSD(nn)) -! + IF (.NOT. ALLOCATED(obj%linFacetCellElemSD)) & & ALLOCATE (obj%linFacetCellElemSD(nn)) -! + IF (.NOT. ALLOCATED(obj%facetElemSD)) & & ALLOCATE (obj%facetElemSD(nn)) -! + IF (.NOT. ALLOCATED(obj%facetCellElemSD)) & & ALLOCATE (obj%facetCellElemSD(nn)) -! + obj%quadTypeForFacet = TRIM(quadTypeForSpace) obj%continuityTypeForFacet = TRIM(continuityTypeForSpace) obj%interpolTypeForFacet = TRIM(interpolTypeForSpace) obj%orderFacet = orderSpace -! + DO ii = 1, nn - ! + CALL Initiate(obj=obj%quadForFacet(ii), & & refelem=spaceElem(ii), & & order=orderSpace, & & QuadratureType=quadTypeForSpace) - ! + CALL Initiate(obj=obj%linFacetElemSD(ii), & & quad=obj%quadForFacet(ii), & & refelem=linSpaceElem(ii), & & ContinuityType=continuityTypeForSpace, & & InterpolType=interpolTypeForSpace) - ! + CALL Initiate(obj=obj%facetElemSD(ii), & & quad=obj%quadForFacet(ii), & & refelem=spaceElem(ii), & & ContinuityType=continuityTypeForSpace, & & InterpolType=interpolTypeForSpace) - ! + faceNptrs = getConnectivity(obj%facetElements(ii)) xijCell = LocalNodeCoord(obj%refelem) CALL getInterpolation(obj=obj%facetElemSD(ii), & & interpol=quadPointsCell, val=xijCell(:, faceNptrs)) - ! + CALL Reallocate(points, obj%nsd + 1, SIZE(quadPointsCell, 2)) points(1:obj%nsd, :) = quadPointsCell(1:obj%nsd, :) CALL Initiate(obj%quadForFacetCell(ii), points=points) - ! + CALL Initiate(obj=obj%linFacetCellElemSD(ii), & & quad=obj%quadForFacetCell(ii), & & refelem=obj%linSpaceElemSD%refelem, & & ContinuityType=continuityTypeForSpace, & & InterpolType=interpolTypeForSpace) - ! + CALL Initiate(obj=obj%facetCellElemSD(ii), & & quad=obj%quadForFacetCell(ii), & & refelem=obj%spaceElemSD%refelem, & & ContinuityType=continuityTypeForSpace, & & InterpolType=interpolTypeForSpace) - ! + END DO -! + END PROCEDURE mesh_initiateFacetElemSD1 !---------------------------------------------------------------------------- diff --git a/src/submodules/MeshSelection/src/MeshSelection_Class@ConstructorMethods.F90 b/src/submodules/MeshSelection/src/MeshSelection_Class@ConstructorMethods.F90 index 45b9374c3..651be5ef8 100644 --- a/src/submodules/MeshSelection/src/MeshSelection_Class@ConstructorMethods.F90 +++ b/src/submodules/MeshSelection/src/MeshSelection_Class@ConstructorMethods.F90 @@ -20,51 +20,136 @@ SUBMODULE(MeshSelection_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! Initiate +! CheckEssentialParam !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_Initiate -IF (.NOT. obj%isInitiated) THEN - obj%isInitiated = .TRUE. - IF (PRESENT(isSelectionByMeshID)) THEN - obj%isSelectionByMeshID = isSelectionByMeshID - ELSE - obj%isSelectionByMeshID = .FALSE. - END IF - IF (PRESENT(isSelectionByElemNum)) THEN - obj%isSelectionByElemNum = isSelectionByElemNum - ELSE - obj%isSelectionByElemNum = .FALSE. - END IF - IF (PRESENT(isSelectionByNodeNum)) THEN - obj%isSelectionByNodeNum = isSelectionByNodeNum - ELSE - obj%isSelectionByNodeNum = .FALSE. - END IF - IF (PRESENT(isSelectionByBox)) THEN - obj%isSelectionByBox = isSelectionByBox - ELSE - obj%isSelectionByBox = .FALSE. - END IF +MODULE PROCEDURE meshSelect_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "meshSelect_CheckEssentialParam()" +INTEGER(I4B) :: ii +TYPE(String), ALLOCATABLE :: essentialParam(:) +TYPE(String) :: astr, prefix0 + +IF (PRESENT(prefix)) THEN + prefix0 = prefix ELSE - IF (PRESENT(isSelectionByMeshID)) THEN - obj%isSelectionByMeshID = isSelectionByMeshID - END IF - IF (PRESENT(isSelectionByElemNum)) THEN - obj%isSelectionByElemNum = isSelectionByElemNum - END IF - IF (PRESENT(isSelectionByNodeNum)) THEN - obj%isSelectionByNodeNum = isSelectionByNodeNum - END IF - IF (PRESENT(isSelectionByBox)) THEN - obj%isSelectionByBox = isSelectionByBox - END IF + prefix0 = obj%GetPrefix() END IF -END PROCEDURE meshSelect_Initiate + +astr = "/isSelectionByMeshID/isSelectionBynodeNum/"// & + & "isSelectionByBox/isSelectionByElemNum" + +CALL astr%Split(essentialParam, sep="/") +CALL CheckEssentialParam(obj=param, & + & keys=essentialParam, & + & prefix=prefix0%chars(), & + & myName=myName, & + & modName=modName) +!NOTE: CheckEssentialParam param is defined in easifemClasses FPL_Method + +IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" + END DO + DEALLOCATE (essentialParam) +END IF +astr = "" +prefix0 = "" +END PROCEDURE meshSelect_CheckEssentialParam + +!---------------------------------------------------------------------------- +! SetMeshSelectionParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetMeshSelectionParam +! CHARACTER(*), PARAMETER :: myName = "SetMeshSelectionParam()" + +CALL Set(param, datatype=.TRUE., prefix=prefix, & + & key="isSelectionByElemNum", & + & VALUE=input(option=isSelectionByElemNum, default=.FALSE.)) + +CALL Set(param, datatype=.TRUE., prefix=prefix, & + & key="isSelectionBynodeNum", & + & VALUE=input(option=isSelectionBynodeNum, default=.FALSE.)) + +CALL Set(param, datatype=.TRUE., prefix=prefix, & + & key="isSelectionByBox", & + & VALUE=input(option=isSelectionByBox, default=.FALSE.)) + +CALL Set(param, datatype=.TRUE., prefix=prefix, & + & key="isSelectionByMeshID", & + & VALUE=input(option=isSelectionByMeshID, default=.FALSE.)) + +END PROCEDURE SetMeshSelectionParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE meshSelect_Initiate1 +CHARACTER(*), PARAMETER :: myName = "meshSelect_Initiate1()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +CALL obj%DEALLOCATE() + +obj%isInitiated = .TRUE. +obj%isSelectionByMeshID = Input(option=isSelectionByMeshID, & + & default=.FALSE.) + +obj%isSelectionByElemNum = Input(option=isSelectionByElemNum, & + & default=.FALSE.) + +obj%isSelectionBynodeNum = Input(option=isSelectionBynodeNum, & + & default=.FALSE.) + +obj%isSelectionByBox = Input(option=isSelectionByBox, & + & default=.FALSE.) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif +END PROCEDURE meshSelect_Initiate1 + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE meshSelect_Initiate2 +CHARACTER(*), PARAMETER :: myName = "meshSelect_Initiate2()" +CHARACTER(:), ALLOCATABLE :: prefix + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] meshSelect_Initiate2()') +#endif + +CALL obj%DEALLOCATE() +obj%isInitiated = .TRUE. +prefix = obj%GetPrefix() +CALL GetValue(obj=param, prefix=prefix, key="isSelectionByBox", & + & VALUE=obj%isSelectionByBox) +CALL GetValue(obj=param, prefix=prefix, key="isSelectionByMeshID", & + & VALUE=obj%isSelectionByMeshID) +CALL GetValue(obj=param, prefix=prefix, key="isSelectionBynodeNum", & + & VALUE=obj%isSelectionBynodeNum) +CALL GetValue(obj=param, prefix=prefix, key="isSelectionByElemNum", & + & VALUE=obj%isSelectionByElemNum) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] meshSelect_Initiate2()') +#endif + +END PROCEDURE meshSelect_Initiate2 !---------------------------------------------------------------------------- ! Deallocate @@ -73,18 +158,26 @@ MODULE PROCEDURE meshSelect_Deallocate obj%isInitiated = .FALSE. obj%isSelectionByElemNum = .FALSE. -obj%isSelectionByNodeNum = .FALSE. +obj%isSelectionBynodeNum = .FALSE. obj%isSelectionByMeshID = .FALSE. obj%isSelectionByBox = .FALSE. -CALL DEALLOCATE (obj%PointMeshID) -CALL DEALLOCATE (obj%CurveMeshID) -CALL DEALLOCATE (obj%SurfaceMeshID) -CALL DEALLOCATE (obj%VolumeMeshID) -CALL DEALLOCATE (obj%PointElemNum) -CALL DEALLOCATE (obj%CurveElemNum) -CALL DEALLOCATE (obj%SurfaceElemNum) -CALL DEALLOCATE (obj%VolumeElemNum) -CALL DEALLOCATE (obj%NodeNum) +CALL DEALLOCATE (obj%pointMeshID) +CALL DEALLOCATE (obj%curveMeshID) +CALL DEALLOCATE (obj%surfaceMeshID) +CALL DEALLOCATE (obj%volumeMeshID) +CALL DEALLOCATE (obj%pointElemNum) +CALL DEALLOCATE (obj%curveElemNum) +CALL DEALLOCATE (obj%surfaceElemNum) +CALL DEALLOCATE (obj%volumeElemNum) +CALL DEALLOCATE (obj%nodeNum) +CALL DEALLOCATE (obj%pointNodeNum) +CALL DEALLOCATE (obj%curveNodeNum) +CALL DEALLOCATE (obj%surfaceNodeNum) +CALL DEALLOCATE (obj%volumeNodeNum) +CALL DEALLOCATE (obj%pointBox) +CALL DEALLOCATE (obj%curveBox) +CALL DEALLOCATE (obj%surfaceBox) +CALL DEALLOCATE (obj%volumeBox) END PROCEDURE meshSelect_Deallocate !---------------------------------------------------------------------------- @@ -103,20 +196,20 @@ obj%isInitiated = obj2%isInitiated obj%isSelectionByMeshID = obj2%isSelectionByMeshID obj%isSelectionByElemNum = obj2%isSelectionByElemNum -obj%isSelectionByNodeNum = obj2%isSelectionByNodeNum +obj%isSelectionBynodeNum = obj2%isSelectionBynodeNum obj%isSelectionByBox = obj2%isSelectionByBox -!> -IF (isAllocated(obj2%PointMeshID)) obj%PointMeshID = obj2%PointMeshID -IF (isAllocated(obj2%CurveMeshID)) obj%CurveMeshID = obj2%CurveMeshID -IF (isAllocated(obj2%SurfaceMeshID)) obj%SurfaceMeshID = obj2%SurfaceMeshID -IF (isAllocated(obj2%VolumeMeshID)) obj%VolumeMeshID = obj2%VolumeMeshID -!> -IF (isAllocated(obj2%PointElemNum)) obj%PointElemNum = obj2%PointElemNum -IF (isAllocated(obj2%CurveElemNum)) obj%CurveElemNum = obj2%CurveElemNum -IF (isAllocated(obj2%SurfaceElemNum)) obj%SurfaceElemNum = obj2%SurfaceElemNum -IF (isAllocated(obj2%VolumeElemNum)) obj%VolumeElemNum = obj2%VolumeElemNum -!> -IF (isAllocated(obj2%NodeNum)) obj%NodeNum = obj2%NodeNum + +IF (isAllocated(obj2%pointMeshID)) obj%pointMeshID = obj2%pointMeshID +IF (isAllocated(obj2%curveMeshID)) obj%curveMeshID = obj2%curveMeshID +IF (isAllocated(obj2%surfaceMeshID)) obj%surfaceMeshID = obj2%surfaceMeshID +IF (isAllocated(obj2%volumeMeshID)) obj%volumeMeshID = obj2%volumeMeshID + +IF (isAllocated(obj2%pointElemNum)) obj%pointElemNum = obj2%pointElemNum +IF (isAllocated(obj2%curveElemNum)) obj%curveElemNum = obj2%curveElemNum +IF (isAllocated(obj2%surfaceElemNum)) obj%surfaceElemNum = obj2%surfaceElemNum +IF (isAllocated(obj2%volumeElemNum)) obj%volumeElemNum = obj2%volumeElemNum + +IF (isAllocated(obj2%nodeNum)) obj%nodeNum = obj2%nodeNum END PROCEDURE meshSelect_Copy !---------------------------------------------------------------------------- diff --git a/src/submodules/MeshSelection/src/MeshSelection_Class@GetMethods.F90 b/src/submodules/MeshSelection/src/MeshSelection_Class@GetMethods.F90 index d196d23b5..626f060ff 100644 --- a/src/submodules/MeshSelection/src/MeshSelection_Class@GetMethods.F90 +++ b/src/submodules/MeshSelection/src/MeshSelection_Class@GetMethods.F90 @@ -106,4 +106,12 @@ END IF END PROCEDURE meshSelect_GetQuery +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE meshSelect_GetPrefix +ans = myprefix +END PROCEDURE meshSelect_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 b/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 index accde029d..db7250a0a 100644 --- a/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 +++ b/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 @@ -25,86 +25,75 @@ CONTAINS !---------------------------------------------------------------------------- -! getNodeNum +! GetNodeNum !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_getNodeNum1 +MODULE PROCEDURE meshSelect_GetNodeNum1 IF (isAllocated(obj%NodeNum)) ans = obj%NodeNum -END PROCEDURE meshSelect_getNodeNum1 +END PROCEDURE meshSelect_GetNodeNum1 !---------------------------------------------------------------------------- -! getNodeNum +! GetNodeNum !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_getNodeNum2 +MODULE PROCEDURE meshSelect_GetNodeNum2 TYPE(IntVector_) :: aintvec INTEGER(I4B), ALLOCATABLE :: indx(:) INTEGER(I4B) :: ii -! + ! isSelectionByNodeNum -! IF (obj%isSelectionByNodeNum) THEN - CALL APPEND(aintvec, obj%getNodeNum()) + CALL APPEND(aintvec, obj%GetNodeNum()) END IF -! + ! isSelectionByMeshID -! IF (obj%isSelectionByMeshID) THEN - ! IF (obj%isMeshIDAllocated(dim=dim)) THEN - ! - indx = obj%getMeshID(dim=dim) - ! + indx = obj%GetMeshID(dim=dim) CALL APPEND( & & aintvec, & - & domain%getNptrs(dim=dim, entityNum=indx)) - ! + & domain%GetNptrs(dim=dim, entityNum=indx)) IF (ALLOCATED(indx)) DEALLOCATE (indx) - ! END IF - ! END IF -! + ! isSelectionByElemNum -! IF (obj%isSelectionByElemNum) THEN - ! - indx = obj%getElemNum(dim=dim) - ! + indx = obj%GetElemNum(dim=dim) DO ii = 1, SIZE(indx) - ! CALL APPEND( & & aintvec, & - & domain%getConnectivity(globalElement=indx(ii))) - ! + & domain%GetConnectivity(globalElement=indx(ii))) END DO - ! IF (ALLOCATED(indx)) DEALLOCATE (indx) - ! END IF -! + IF (isAllocated(aIntVec)) THEN CALL RemoveDuplicates(aIntVec) ans = aIntVec CALL DEALLOCATE (aIntVec) END IF -! -END PROCEDURE meshSelect_getNodeNum2 + +END PROCEDURE meshSelect_GetNodeNum2 !---------------------------------------------------------------------------- -! getNodeNum +! GetNodeNum !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_getNodeNum3 -CHARACTER(*), PARAMETER :: myName = "meshSelect_getNodeNum3" +MODULE PROCEDURE meshSelect_GetNodeNum3 +CHARACTER(*), PARAMETER :: myName = "meshSelect_GetNodeNum3" TYPE(IntVector_) :: aintvec INTEGER(I4B), ALLOCATABLE :: indx(:), nptrs(:) INTEGER(I4B) :: ii, dim, nsd -! isSelectionByNodeNum +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GetNodeNum()') +#endif +! isSelectionByNodeNum IF (obj%isSelectionByNodeNum) THEN - nptrs = obj%getNodeNum() + nptrs = obj%GetNodeNum() IF (ALLOCATED(nptrs)) THEN CALL APPEND(aintvec, nptrs) DEALLOCATE (nptrs) @@ -112,55 +101,42 @@ END IF ! isSelectionByMeshID - IF (obj%isSelectionByMeshID) THEN - - nsd = domain%getNSD() - + nsd = domain%GetNSD() DO dim = 0, nsd - IF (obj%isMeshIDAllocated(dim=dim)) THEN - - indx = obj%getMeshID(dim=dim) - - nptrs = domain%getNptrs(dim=dim, entityNum=indx) + indx = obj%GetMeshID(dim=dim) + nptrs = domain%GetNptrs(dim=dim, entityNum=indx) IF (ALLOCATED(nptrs)) THEN CALL APPEND(aintvec, nptrs) DEALLOCATE (nptrs) END IF - IF (ALLOCATED(indx)) DEALLOCATE (indx) - END IF - END DO - END IF ! isSelectionByElemNum - IF (obj%isSelectionByElemNum) THEN - ! - indx = obj%getElemNum() - ! + indx = obj%GetElemNum() DO ii = 1, SIZE(indx) - ! CALL APPEND( & & aintvec, & - & domain%getConnectivity(globalElement=indx(ii))) - ! + & domain%GetConnectivity(globalElement=indx(ii))) END DO - ! IF (ALLOCATED(indx)) DEALLOCATE (indx) - ! END IF -! + IF (isAllocated(aIntVec)) THEN CALL RemoveDuplicates(aIntVec) ans = aIntVec CALL DEALLOCATE (aIntVec) END IF -! -END PROCEDURE meshSelect_getNodeNum3 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GetNodeNum()') +#endif +END PROCEDURE meshSelect_GetNodeNum3 END SUBMODULE GetNodeNumMethods diff --git a/src/submodules/MeshSelection/src/MeshSelection_Class@IOMethods.F90 b/src/submodules/MeshSelection/src/MeshSelection_Class@IOMethods.F90 index 5e9b73d0f..ca1c761be 100644 --- a/src/submodules/MeshSelection/src/MeshSelection_Class@IOMethods.F90 +++ b/src/submodules/MeshSelection/src/MeshSelection_Class@IOMethods.F90 @@ -18,8 +18,21 @@ ! date: 28 Aug 2021 ! summary: This module defines a data type for mesh selection -SUBMODULE (MeshSelection_Class) IOMethods +SUBMODULE(MeshSelection_Class) IOMethods USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_error, & + & toml_load, & + & toml_parser_config, & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_context, & + & toml_terminal, & + & toml_load, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS @@ -28,136 +41,141 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE meshSelect_Import - CHARACTER( LEN = * ), PARAMETER :: myName="meshSelect_Import" - TYPE( String ) :: dsetname, strval - INTEGER( I4B ) :: ierr - INTEGER( I4B ), ALLOCATABLE :: intvec( : ) - !> check - !> print info - CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Importing Mesh Selection") - IF( obj%isInitiated ) THEN - CALL e%raiseError(modName//'::'//myName// " - "// & - & 'The object is already initiated, deallocate first!') - END IF - obj%isInitiated = .TRUE. - !> check - IF( .NOT. hdf5%isOpen() ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') - END IF - !> check - IF( .NOT. hdf5%isRead() ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have read permission') - END IF - ! READ isSelectionByMeshID - dsetname=TRIM(group)//"/isSelectionByMeshID" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByMeshID) - ELSE - obj%isSelectionByMeshID=.FALSE. - END IF - ! READ isSelectionByElemNum - dsetname=TRIM(group)//"/isSelectionByElemNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByElemNum) - ELSE - obj%isSelectionByElemNum=.FALSE. - END IF - ! READ isSelectionByNodeNum - dsetname=TRIM(group)//"/isSelectionByNodeNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByNodeNum) - ELSE - obj%isSelectionByNodeNum=.FALSE. - END IF - ! READ isSelectionByBox - dsetname=TRIM(group)//"/isSelectionByBox" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByBox) - ELSE - obj%isSelectionByBox=.FALSE. - END IF - ! READ PointMeshID - dsetname=TRIM(group)//"/PointMeshID" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%PointMeshID=intvec - obj%isSelectionByMeshID=.TRUE. - END IF - ! READ CurveMeshID - dsetname=TRIM(group)//"/CurveMeshID" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%CurveMeshID=intvec - obj%isSelectionByMeshID=.TRUE. - END IF - ! READ SurfaceMeshID - dsetname=TRIM(group)//"/SurfaceMeshID" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%SurfaceMeshID=intvec - obj%isSelectionByMeshID=.TRUE. - END IF - ! READ VolumeMeshID - dsetname=TRIM(group)//"/VolumeMeshID" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%VolumeMeshID=intvec - obj%isSelectionByMeshID=.TRUE. - END IF - ! READ PointElemNum - dsetname=TRIM(group)//"/PointElemNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%PointElemNum=intvec - obj%isSelectionByElemNum=.TRUE. - END IF - ! READ CurveElemNum - dsetname=TRIM(group)//"/CurveElemNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%CurveElemNum=intvec - obj%isSelectionByElemNum=.TRUE. - END IF - ! READ SurfaceElemNum - dsetname=TRIM(group)//"/SurfaceElemNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%SurfaceElemNum=intvec - obj%isSelectionByElemNum=.TRUE. - END IF - ! READ VolumeElemNum - dsetname=TRIM(group)//"/VolumeElemNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%VolumeElemNum=intvec - obj%isSelectionByElemNum=.TRUE. - END IF - ! READ NodeNum - dsetname=TRIM(group)//"/NodeNum" - IF( hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%read(dsetname=dsetname%chars(), & - & vals=intvec) - obj%NodeNum=intvec - obj%isSelectionByNodeNum =.TRUE. - END IF - !> print info - CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Importing Mesh Selection [OK!]") +CHARACTER(*), PARAMETER :: myName = "meshSelect_Import" +TYPE(String) :: dsetname +INTEGER(I4B), ALLOCATABLE :: intvec(:) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +IF (obj%isInitiated) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: MeshSelection_::object is already initiated, '// & + & 'deallocate it first!') +END IF + +obj%isInitiated = .TRUE. + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'HDF5 file is not opened') +END IF +!> check +IF (.NOT. hdf5%isRead()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'HDF5 file does not have read permission') +END IF +! READ isSelectionByMeshID +dsetname = TRIM(group)//"/isSelectionByMeshID" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByMeshID) +ELSE + obj%isSelectionByMeshID = .FALSE. +END IF +! READ isSelectionByElemNum +dsetname = TRIM(group)//"/isSelectionByElemNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByElemNum) +ELSE + obj%isSelectionByElemNum = .FALSE. +END IF +! READ isSelectionByNodeNum +dsetname = TRIM(group)//"/isSelectionByNodeNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByNodeNum) +ELSE + obj%isSelectionByNodeNum = .FALSE. +END IF +! READ isSelectionByBox +dsetname = TRIM(group)//"/isSelectionByBox" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByBox) +ELSE + obj%isSelectionByBox = .FALSE. +END IF +! READ PointMeshID +dsetname = TRIM(group)//"/PointMeshID" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%PointMeshID = intvec + obj%isSelectionByMeshID = .TRUE. +END IF +! READ CurveMeshID +dsetname = TRIM(group)//"/CurveMeshID" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%CurveMeshID = intvec + obj%isSelectionByMeshID = .TRUE. +END IF +! READ SurfaceMeshID +dsetname = TRIM(group)//"/SurfaceMeshID" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%SurfaceMeshID = intvec + obj%isSelectionByMeshID = .TRUE. +END IF +! READ VolumeMeshID +dsetname = TRIM(group)//"/VolumeMeshID" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%VolumeMeshID = intvec + obj%isSelectionByMeshID = .TRUE. +END IF +! READ PointElemNum +dsetname = TRIM(group)//"/PointElemNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%PointElemNum = intvec + obj%isSelectionByElemNum = .TRUE. +END IF +! READ CurveElemNum +dsetname = TRIM(group)//"/CurveElemNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%CurveElemNum = intvec + obj%isSelectionByElemNum = .TRUE. +END IF +! READ SurfaceElemNum +dsetname = TRIM(group)//"/SurfaceElemNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%SurfaceElemNum = intvec + obj%isSelectionByElemNum = .TRUE. +END IF +! READ VolumeElemNum +dsetname = TRIM(group)//"/VolumeElemNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%VolumeElemNum = intvec + obj%isSelectionByElemNum = .TRUE. +END IF +! READ NodeNum +dsetname = TRIM(group)//"/NodeNum" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), & + & vals=intvec) + obj%NodeNum = intvec + obj%isSelectionByNodeNum = .TRUE. +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif END PROCEDURE meshSelect_Import !---------------------------------------------------------------------------- @@ -165,110 +183,109 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE meshSelect_Export - CHARACTER( LEN = * ), PARAMETER :: myName="meshSelect_Export" - TYPE( String ) :: dsetname, strval - INTEGER( I4B ) :: ierr - INTEGER( I4B ), ALLOCATABLE :: intvec( : ) - !> print info - CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Exporting Mesh Selection") - !> check - IF( .NOT. obj%isInitiated ) THEN - CALL e%raiseError(modName//'::'//myName// " - "// & - & 'The object is not initiated, allocate first!') - END IF - !> check - IF( .NOT. hdf5%isOpen() ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') - END IF - !> check - IF( .NOT. hdf5%isWrite() ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have write permission') - END IF - ! READ isSelectionByMeshID - dsetname=TRIM(group)//"/isSelectionByMeshID" - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByMeshID) - ! READ isSelectionByElemNum - dsetname=TRIM(group)//"/isSelectionByElemNum" - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByElemNum) - ! READ isSelectionByNodeNum - dsetname=TRIM(group)//"/isSelectionByNodeNum" - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByNodeNum) - ! READ isSelectionByBox - dsetname=TRIM(group)//"/isSelectionByBox" - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=obj%isSelectionByBox) - ! READ PointMeshID - IF( isAllocated(obj%PointMeshID) ) THEN - dsetname=TRIM(group)//"/PointMeshID" - intvec=obj%PointMeshID - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ CurveMeshID - IF( isAllocated(obj%CurveMeshID) ) THEN - dsetname=TRIM(group)//"/CurveMeshID" - intvec=obj%CurveMeshID - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ SurfaceMeshID - IF( isAllocated(obj%SurfaceMeshID) ) THEN - dsetname=TRIM(group)//"/SurfaceMeshID" - intvec=obj%SurfaceMeshID - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ VolumeMeshID - IF( isAllocated(obj%VolumeMeshID) ) THEN - dsetname=TRIM(group)//"/VolumeMeshID" - intvec=obj%VolumeMeshID - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ PointElemNum - IF( isAllocated(obj%PointElemNum) ) THEN - dsetname=TRIM(group)//"/PointElemNum" - intvec=obj%PointElemNum - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ CurveElemNum - IF( isAllocated(obj%CurveElemNum) ) THEN - dsetname=TRIM(group)//"/CurveElemNum" - intvec=obj%CurveElemNum - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ SurfaceElemNum - IF( isAllocated(obj%SurfaceElemNum) ) THEN - dsetname=TRIM(group)//"/SurfaceElemNum" - intvec=obj%SurfaceElemNum - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ VolumeElemNum - IF( isAllocated(obj%VolumeElemNum) ) THEN - dsetname=TRIM(group)//"/VolumeElemNum" - intvec=obj%VolumeElemNum - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - ! READ NodeNum - IF( isAllocated(obj%NodeNum) ) THEN - dsetname=TRIM(group)//"/NodeNum" - intvec=obj%NodeNum - CALL hdf5%write(dsetname=dsetname%chars(), & - & vals=intvec) - END IF - !> print info - CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Exporting Mesh Selection [OK!]") +CHARACTER(*), PARAMETER :: myName = "meshSelect_Export" +TYPE(String) :: dsetname +INTEGER(I4B), ALLOCATABLE :: intvec(:) +!> print info +CALL e%RaiseInformation(modName//"::"//myName//" - "// & + & "Exporting Mesh Selection") +!> check +IF (.NOT. obj%isInitiated) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The object is not initiated, allocate first!') +END IF +!> check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'HDF5 file is not opened') +END IF +!> check +IF (.NOT. hdf5%isWrite()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'HDF5 file does not have write permission') +END IF +! READ isSelectionByMeshID +dsetname = TRIM(group)//"/isSelectionByMeshID" +CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByMeshID) +! READ isSelectionByElemNum +dsetname = TRIM(group)//"/isSelectionByElemNum" +CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByElemNum) +! READ isSelectionByNodeNum +dsetname = TRIM(group)//"/isSelectionByNodeNum" +CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByNodeNum) +! READ isSelectionByBox +dsetname = TRIM(group)//"/isSelectionByBox" +CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=obj%isSelectionByBox) +! READ PointMeshID +IF (isAllocated(obj%PointMeshID)) THEN + dsetname = TRIM(group)//"/PointMeshID" + intvec = obj%PointMeshID + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ CurveMeshID +IF (isAllocated(obj%CurveMeshID)) THEN + dsetname = TRIM(group)//"/CurveMeshID" + intvec = obj%CurveMeshID + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ SurfaceMeshID +IF (isAllocated(obj%SurfaceMeshID)) THEN + dsetname = TRIM(group)//"/SurfaceMeshID" + intvec = obj%SurfaceMeshID + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ VolumeMeshID +IF (isAllocated(obj%VolumeMeshID)) THEN + dsetname = TRIM(group)//"/VolumeMeshID" + intvec = obj%VolumeMeshID + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ PointElemNum +IF (isAllocated(obj%PointElemNum)) THEN + dsetname = TRIM(group)//"/PointElemNum" + intvec = obj%PointElemNum + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ CurveElemNum +IF (isAllocated(obj%CurveElemNum)) THEN + dsetname = TRIM(group)//"/CurveElemNum" + intvec = obj%CurveElemNum + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ SurfaceElemNum +IF (isAllocated(obj%SurfaceElemNum)) THEN + dsetname = TRIM(group)//"/SurfaceElemNum" + intvec = obj%SurfaceElemNum + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ VolumeElemNum +IF (isAllocated(obj%VolumeElemNum)) THEN + dsetname = TRIM(group)//"/VolumeElemNum" + intvec = obj%VolumeElemNum + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +! READ NodeNum +IF (isAllocated(obj%NodeNum)) THEN + dsetname = TRIM(group)//"/NodeNum" + intvec = obj%NodeNum + CALL hdf5%WRITE(dsetname=dsetname%chars(), & + & vals=intvec) +END IF +!> print info +CALL e%RaiseInformation(modName//"::"//myName//" - "// & + & "Exporting Mesh Selection [OK!]") END PROCEDURE meshSelect_Export !---------------------------------------------------------------------------- @@ -276,61 +293,446 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE meshSelect_Display - IF( LEN_TRIM( msg ) .GT. 0 ) THEN - CALL Display( "# "//TRIM(msg), unitNo=unitNo ) - END IF - IF( .NOT. obj%isInitiated ) THEN - CALL Display( "# The object is not initiated, nothing to show!", & +LOGICAL(LGT) :: bool1 +INTEGER(I4B) :: ii + +CALL EqualLine(unitNo=unitNo) +CALL Display(msg, unitNo=unitNo) +CALL EqualLine(unitNo=unitNo) +IF (.NOT. obj%isInitiated) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display("The object is not initiated, nothing to show!", & + & unitNo=unitNo) + RETURN + CALL EqualLine(unitNo=unitNo) +END IF + +CALL BlankLines(unitNo=unitNo, nol=1_I4B) +CALL Display(obj%isInitiated, "IsInitiated :", unitNo=unitNo) +CALL Display(obj%IsSelectionByMeshID, "IsSelectionByMeshID : ", & + & unitNo=unitNo) +CALL Display(obj%IsSelectionByElemNum, "IsSelectionByElemNum : ", & + & unitNo=unitNo) +CALL Display(obj%IsSelectionByNodeNum, "IsSelectionByNodeNum : ", & + & unitNo=unitNo) +CALL Display(obj%IsSelectionByBox, "IsSelectionByBox : ", & + & unitNo=unitNo) +bool1 = IsAllocated(obj%pointMeshID) +CALL Display(bool1, "PointMeshID ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%curveMeshID) +CALL Display(bool1, "CurveMeshID ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%surfaceMeshID) +CALL Display(bool1, "SurfaceMeshID ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%volumeMeshID) +CALL Display(bool1, "VolumeMeshID ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%pointElemNum) +CALL Display(bool1, "PointElemNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%curveElemNum) +CALL Display(bool1, "CurveElemNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%surfaceElemNum) +CALL Display(bool1, "SurfaceElemNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%volumeElemNum) +CALL Display(bool1, "VolumeElemNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%pointNodeNum) +CALL Display(bool1, "PointNodeNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%curveNodeNum) +CALL Display(bool1, "CurveNodeNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%surfaceNodeNum) +CALL Display(bool1, "SurfaceNodeNum ALLOCATED :", unitNo=unitNo) +bool1 = IsAllocated(obj%volumeNodeNum) +CALL Display(bool1, "VolumeNodeNum ALLOCATED :", unitNo=unitNo) +bool1 = ALLOCATED(obj%pointBox) +CALL Display(bool1, "PointBox ALLOCATED :", unitNo=unitNo) +bool1 = ALLOCATED(obj%curveBox) +CALL Display(bool1, "CurveBox ALLOCATED :", unitNo=unitNo) +bool1 = ALLOCATED(obj%surfaceBox) +CALL Display(bool1, "SurfaceBox ALLOCATED :", unitNo=unitNo) +bool1 = ALLOCATED(obj%volumeBox) +CALL Display(bool1, "VolumeBox ALLOCATED :", unitNo=unitNo) + +bool1 = IsAllocated(obj%pointMeshID) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%pointMeshID, "PointMeshID : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%curveMeshID) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%curveMeshID, "CurveMeshID : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%surfaceMeshID) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%surfaceMeshID, "SurfaceMeshID : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%volumeMeshID) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%volumeMeshID, "VolumeMeshID : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%pointElemNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%pointElemNum, "PointElemNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%curveElemNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%curveElemNum, "CurveElemNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%surfaceElemNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%surfaceElemNum, "SurfaceElemNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%volumeElemNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%volumeElemNum, "VolumeElemNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%pointNodeNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%pointNodeNum, "PointNodeNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%curveNodeNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%curveNodeNum, "CurveNodeNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%surfaceNodeNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%surfaceNodeNum, "SurfaceNodeNum : ", unitNo=unitNo) +END IF + +bool1 = IsAllocated(obj%volumeNodeNum) +IF (bool1) THEN + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%volumeNodeNum, "VolumeNodeNum : ", unitNo=unitNo) +END IF + +bool1 = ALLOCATED(obj%pointBox) +IF (bool1) THEN + DO ii = 1, SIZE(obj%pointBox) + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%pointBox(ii), "PointBox("//tostring(ii)//") : ", & + & unitNo=unitNo) + END DO +END IF + +bool1 = ALLOCATED(obj%curveBox) +IF (bool1) THEN + DO ii = 1, SIZE(obj%curveBox) + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%curveBox(ii), "curveBox("//tostring(ii)//") : ", & + & unitNo=unitNo) + END DO +END IF + +bool1 = ALLOCATED(obj%surfaceBox) +IF (bool1) THEN + DO ii = 1, SIZE(obj%surfaceBox) + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%surfaceBox(ii), "surfaceBox("//tostring(ii)//") : ", & & unitNo=unitNo) - RETURN - ELSE - CALL Display( "# isInitiated : TRUE" , & + END DO +END IF + +bool1 = ALLOCATED(obj%volumeBox) +IF (bool1) THEN + DO ii = 1, SIZE(obj%volumeBox) + CALL BlankLines(unitNo=unitNo, nol=1_I4B) + CALL Display(obj%volumeBox(ii), "volumeBox("//tostring(ii)//") : ", & & unitNo=unitNo) - END IF - CALL Display( obj%isSelectionByMeshID, "# isSelectionByMeshID : ", & - & unitNo=unitNo ) - CALL Display( obj%isSelectionByElemNum, "# isSelectionByElemNum : ", & - & unitNo=unitNo ) - CALL Display( obj%isSelectionByNodeNum, "# isSelectionByNodeNum : ", & - & unitNo=unitNo ) - CALL Display( obj%isSelectionByBox, "# isSelectionByBox : ", & - & unitNo=unitNo ) - IF( isAllocated( obj%PointMeshID ) ) THEN - CALL Display( obj%PointMeshID, "PointMeshID : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%CurveMeshID ) ) THEN - CALL Display( obj%CurveMeshID, "CurveMeshID : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%SurfaceMeshID ) ) THEN - CALL Display( obj%SurfaceMeshID, "SurfaceMeshID : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%VolumeMeshID ) ) THEN - CALL Display( obj%VolumeMeshID, "VolumeMeshID : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%PointElemNum ) ) THEN - CALL Display( obj%PointElemNum, "PointElemNum : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%CurveElemNum ) ) THEN - CALL Display( obj%CurveElemNum, "CurveElemNum : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%SurfaceElemNum ) ) THEN - CALL Display( obj%SurfaceElemNum, "SurfaceElemNum : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%VolumeElemNum ) ) THEN - CALL Display( obj%VolumeElemNum, "VolumeElemNum : ", & - & unitNo=unitNo ) - END IF - IF( isAllocated( obj%NodeNum ) ) THEN - CALL Display( obj%NodeNum, "NodeNum : ", & - & unitNo=unitNo ) - END IF + END DO +END IF + END PROCEDURE meshSelect_Display -END SUBMODULE IOMethods \ No newline at end of file +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE meshSelect_ImportParamFromToml +CHARACTER(*), PARAMETER :: myName = "meshSelect_ImportParamFromToml()" +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: isSelectionByElemNum, isSelectionByNodeNum, & + & isSelectionByBox, isSelectionByMeshID + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportParamFromToml()') +#endif + +CALL toml_get(table, "isSelectionByMeshID", isSelectionByMeshID, & + & .FALSE., origin=origin, stat=stat) + +CALL toml_get(table, "isSelectionByNodeNum", isSelectionByNodeNum, & + & .FALSE., origin=origin, stat=stat) + +CALL toml_get(table, "isSelectionByBox", isSelectionByBox, & + & .FALSE., origin=origin, stat=stat) + +CALL toml_get(table, "isSelectionByElemNum", isSelectionByElemNum, & + & .FALSE., origin=origin, stat=stat) + +CALL SetMeshSelectionParam( & + & param=param, & + & prefix=obj%GetPrefix(), & + & isSelectionByMeshID=isSelectionByMeshID, & + & isSelectionByNodeNum=isSelectionByNodeNum, & + & isSelectionByBox=isSelectionByBox, & + & isSelectionByElemNum=isSelectionByElemNum & + & ) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE meshSelect_ImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE meshSelect_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "meshSelect_ImportFromToml1()" +TYPE(ParameterList_) :: param +INTEGER(I4B), ALLOCATABLE :: aintvec(:) +TYPE(BoundingBox_), ALLOCATABLE :: box(:) +LOGICAL(LGT) :: bool1, isFound +TYPE(toml_table), POINTER :: node +INTEGER(I4B) :: origin, stat + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +CALL param%Initiate() +CALL obj%ImportParamFromToml(param=param, table=table) +CALL obj%Initiate(param) +CALL param%DEALLOCATE() + +! meshID +node => NULL() +CALL toml_get(table, "meshID", node, origin=origin, & + & stat=stat, requested=.FALSE.) + +bool1 = obj%isSelectionByMeshID .AND. (.NOT. ASSOCIATED(node)) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: You have set isSelectionByMeshID = .TRUE.'// & + & ' but you have not provided meshID table.') + RETURN +END IF + +bool1 = ASSOCIATED(node) .AND. (.NOT. obj%isSelectionByMeshID) +IF (bool1) obj%isSelectionByMeshID = .TRUE. + +IF (ASSOCIATED(node)) THEN + ! read points + CALL GetValue(table=node, key="point", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=0_I4B, meshID=aintvec, dom=dom) + + ! read lines + CALL GetValue(table=node, key="line", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=1_I4B, meshID=aintvec, dom=dom) + + ! read surfaces + CALL GetValue(table=node, key="surface", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=2_I4B, meshID=aintvec, dom=dom) + + ! read volumes + CALL GetValue(table=node, key="volume", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=3_I4B, meshID=aintvec, dom=dom) +END IF + +! box +node => NULL() +CALL toml_get(table, "box", node, origin=origin, & + & stat=stat, requested=.FALSE.) + +bool1 = obj%isSelectionByBox .AND. (.NOT. ASSOCIATED(node)) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: You have set isSelectionByBox = .TRUE.'// & + & ' but you have not provided [box] table.') + RETURN +END IF + +bool1 = ASSOCIATED(node) .AND. (.NOT. obj%isSelectionByBox) +IF (bool1) obj%isSelectionByBox = .TRUE. + +IF (ASSOCIATED(node)) THEN + ! read points + CALL GetValue(table=node, key="point", VALUE=box, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=0_I4B, box=box, dom=dom) + + ! read lines + CALL GetValue(table=node, key="line", VALUE=box, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=1_I4B, box=box, dom=dom) + + ! read surfaces + CALL GetValue(table=node, key="surface", VALUE=box, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=2_I4B, box=box, dom=dom) + + ! read volumes + CALL GetValue(table=node, key="volume", VALUE=box, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=3_I4B, box=box, dom=dom) +END IF + +! elemNum +node => NULL() +CALL toml_get(table, "elemNum", node, origin=origin, & + & stat=stat, requested=.FALSE.) + +bool1 = obj%isSelectionByElemNum .AND. (.NOT. ASSOCIATED(node)) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: You have set isSelectionByElemNum = .TRUE.'// & + & ' but you have not provided [elemNum] table.') + RETURN +END IF + +bool1 = ASSOCIATED(node) .AND. (.NOT. obj%isSelectionByElemNum) +IF (bool1) obj%isSelectionByElemNum = .TRUE. + +IF (ASSOCIATED(node)) THEN + ! read points + CALL GetValue(table=node, key="point", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=0_I4B, elemNum=aintvec, dom=dom) + + ! read lines + CALL GetValue(table=node, key="line", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=1_I4B, elemNum=aintvec, dom=dom) + + ! read surfaces + CALL GetValue(table=node, key="surface", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=2_I4B, elemNum=aintvec, dom=dom) + + ! read volumes + CALL GetValue(table=node, key="volume", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=3_I4B, elemNum=aintvec, dom=dom) +END IF + +! nodeNum +node => NULL() +CALL toml_get(table, "nodeNum", node, origin=origin, & + & stat=stat, requested=.FALSE.) + +bool1 = obj%isSelectionByElemNum .AND. (.NOT. ASSOCIATED(node)) +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: You have set isSelectionByElemNum = .TRUE.'// & + & ' but you have not provided [nodeNum] table.') + RETURN +END IF + +bool1 = ASSOCIATED(node) .AND. (.NOT. obj%isSelectionByElemNum) +IF (bool1) obj%isSelectionByElemNum = .TRUE. + +IF (ASSOCIATED(node)) THEN + ! read points + CALL GetValue(table=node, key="point", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=0_I4B, nodeNum=aintvec, dom=dom) + + ! read lines + CALL GetValue(table=node, key="line", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=1_I4B, nodeNum=aintvec, dom=dom) + + ! read surfaces + CALL GetValue(table=node, key="surface", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=2_I4B, nodeNum=aintvec, dom=dom) + + ! read volumes + CALL GetValue(table=node, key="volume", VALUE=aintvec, & + & origin=origin, stat=stat, isFound=isFound) + IF (isFound) CALL obj%Add(dim=3_I4B, nodeNum=aintvec, dom=dom) +END IF + +CALL obj%Set() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml()') +#endif +END PROCEDURE meshSelect_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE meshSelect_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "meshSelect_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +INTEGER(I4B) :: origin, stat + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +node => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find ['//tomlName//"] table in config.") +END IF + +CALL obj%ImportFromToml(table=node) + +#ifdef DEBUG_VER +IF (PRESENT(printToml)) THEN + CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & + & unitNo=stdout) +END IF +#endif + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE meshSelect_ImportFromToml2 + +END SUBMODULE IOMethods diff --git a/src/submodules/MeshSelection/src/MeshSelection_Class@SetMethods.F90 b/src/submodules/MeshSelection/src/MeshSelection_Class@SetMethods.F90 index 79e8df4af..f511624bc 100644 --- a/src/submodules/MeshSelection/src/MeshSelection_Class@SetMethods.F90 +++ b/src/submodules/MeshSelection/src/MeshSelection_Class@SetMethods.F90 @@ -28,43 +28,83 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE meshSelect_Add -CHARACTER(LEN=*), PARAMETER :: myName = "meshSelect_Add" -IF (PRESENT(dim) .AND. PRESENT(meshID)) THEN +CHARACTER(*), PARAMETER :: myName = "meshSelect_Add" +LOGICAL(LGT) :: bool1 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Add()') +#endif + +bool1 = PRESENT(dim) .AND. PRESENT(meshID) +IF (bool1) THEN obj%isSelectionByMeshID = .TRUE. SELECT CASE (dim) CASE (0) - CALL APPEND(obj%PointMeshID, meshID) + CALL Append(obj%pointMeshID, meshID) CASE (1) - CALL APPEND(obj%CurveMeshID, meshID) + CALL Append(obj%curveMeshID, meshID) CASE (2) - CALL APPEND(obj%SurfaceMeshID, meshID) + CALL Append(obj%surfaceMeshID, meshID) CASE (3) - CALL APPEND(obj%VolumeMeshID, meshID) + CALL Append(obj%volumeMeshID, meshID) END SELECT - RETURN END IF -IF (PRESENT(dim) .AND. PRESENT(elemNum)) THEN + +bool1 = PRESENT(dim) .AND. PRESENT(elemNum) +IF (bool1) THEN obj%isSelectionByElemNum = .TRUE. SELECT CASE (dim) CASE (0) - CALL APPEND(obj%PointElemNum, elemNum) + CALL Append(obj%pointElemNum, elemNum) CASE (1) - CALL APPEND(obj%CurveElemNum, elemNum) + CALL Append(obj%curveElemNum, elemNum) CASE (2) - CALL APPEND(obj%SurfaceElemNum, elemNum) + CALL Append(obj%surfaceElemNum, elemNum) CASE (3) - CALL APPEND(obj%VolumeElemNum, elemNum) + CALL Append(obj%volumeElemNum, elemNum) END SELECT - RETURN END IF -IF (PRESENT(nodeNum)) THEN + +bool1 = PRESENT(nodeNum) .AND. (.NOT. PRESENT(dim)) +IF (bool1) THEN obj%isSelectionByNodeNum = .TRUE. - CALL APPEND(obj%NodeNum, nodeNum) - RETURN + CALL Append(obj%NodeNum, nodeNum) +END IF + +bool1 = PRESENT(nodeNum) .AND. (PRESENT(dim)) +IF (bool1) THEN + obj%isSelectionByNodeNum = .TRUE. + SELECT CASE (dim) + CASE (0) + CALL Append(obj%pointNodeNum, nodeNum) + CASE (1) + CALL Append(obj%curveNodeNum, nodeNum) + CASE (2) + CALL Append(obj%surfaceNodeNum, nodeNum) + CASE (3) + CALL Append(obj%volumeNodeNum, nodeNum) + END SELECT END IF -CALL e%raiseError(modName//'::'//myName//'-'// & - & 'Currently mesh selection is possible through (xidim, meshID), & - & and (xidim, elemNum). We are working on it') + +bool1 = PRESENT(dim) .AND. PRESENT(box) +IF (bool1) THEN + SELECT CASE (dim) + CASE (0) + CALL Append(obj%pointBox, box) + CASE (1) + CALL Append(obj%curveBox, box) + CASE (2) + CALL Append(obj%surfaceBox, box) + CASE (3) + CALL Append(obj%volumeBox, box) + END SELECT +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Add()') +#endif END PROCEDURE meshSelect_Add !---------------------------------------------------------------------------- @@ -72,29 +112,29 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE meshSelect_Set -IF (isAllocated(obj%PointMeshID)) THEN - CALL RemoveDuplicates(obj%PointMeshID) +IF (isAllocated(obj%pointMeshID)) THEN + CALL RemoveDuplicates(obj%pointMeshID) END IF -IF (isAllocated(obj%CurveMeshID)) THEN - CALL RemoveDuplicates(obj%CurveMeshID) +IF (isAllocated(obj%curveMeshID)) THEN + CALL RemoveDuplicates(obj%curveMeshID) END IF -IF (isAllocated(obj%SurfaceMeshID)) THEN - CALL RemoveDuplicates(obj%SurfaceMeshID) +IF (isAllocated(obj%surfaceMeshID)) THEN + CALL RemoveDuplicates(obj%surfaceMeshID) END IF -IF (isAllocated(obj%VolumeMeshID)) THEN - CALL RemoveDuplicates(obj%VolumeMeshID) +IF (isAllocated(obj%volumeMeshID)) THEN + CALL RemoveDuplicates(obj%volumeMeshID) END IF -IF (isAllocated(obj%PointElemNum)) THEN - CALL RemoveDuplicates(obj%PointElemNum) +IF (isAllocated(obj%pointElemNum)) THEN + CALL RemoveDuplicates(obj%pointElemNum) END IF -IF (isAllocated(obj%CurveElemNum)) THEN - CALL RemoveDuplicates(obj%CurveElemNum) +IF (isAllocated(obj%curveElemNum)) THEN + CALL RemoveDuplicates(obj%curveElemNum) END IF -IF (isAllocated(obj%SurfaceElemNum)) THEN - CALL RemoveDuplicates(obj%SurfaceElemNum) +IF (isAllocated(obj%surfaceElemNum)) THEN + CALL RemoveDuplicates(obj%surfaceElemNum) END IF -IF (isAllocated(obj%VolumeElemNum)) THEN - CALL RemoveDuplicates(obj%VolumeElemNum) +IF (isAllocated(obj%volumeElemNum)) THEN + CALL RemoveDuplicates(obj%volumeElemNum) END IF IF (isAllocated(obj%NodeNum)) THEN CALL RemoveDuplicates(obj%NodeNum) diff --git a/src/submodules/NeumannBC/src/NeumannBC_Class@ConstructorMethods.F90 b/src/submodules/NeumannBC/src/NeumannBC_Class@ConstructorMethods.F90 index e9807fd92..dd0106a51 100644 --- a/src/submodules/NeumannBC/src/NeumannBC_Class@ConstructorMethods.F90 +++ b/src/submodules/NeumannBC/src/NeumannBC_Class@ConstructorMethods.F90 @@ -21,47 +21,7 @@ CONTAINS !---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_checkEssentialParam -CALL AbstractBCcheckEssentialParam(& -& obj=obj, & -& param=param, & -& prefix=myprefix) -END PROCEDURE bc_checkEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE setNeumannBCParam -CALL setAbstractBCParam(& -& param=param, & -& prefix=myprefix, & -& name=name, & -& idof=idof, & -& nodalValueType=nodalValueType, & -& useFunction=input(option=useFunction, default=.FALSE.), & -& isNormal=input(option=isNormal, default=.FALSE.), & -& isTangent=input(option=isTangent, default=.FALSE.) & -& ) -END PROCEDURE setNeumannBCParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_Initiate -CALL AbstractBCInitiate(obj=obj, & -& param=param, & -& prefix=myprefix, & -& boundary=boundary, & -& dom=dom) -END PROCEDURE bc_Initiate - -!---------------------------------------------------------------------------- -! Final +! Final !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Final @@ -69,7 +29,7 @@ END PROCEDURE bc_Final !---------------------------------------------------------------------------- -! Deallocate +! Deallocate !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Deallocate_Vector @@ -83,7 +43,7 @@ END PROCEDURE bc_Deallocate_Vector !---------------------------------------------------------------------------- -! Deallocate +! Deallocate !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Deallocate_Ptr_Vector @@ -100,7 +60,7 @@ END PROCEDURE bc_Deallocate_Ptr_Vector !---------------------------------------------------------------------------- -! AddNeumannBC +! AddNeumannBC !---------------------------------------------------------------------------- MODULE PROCEDURE bc_AddNeumannBC diff --git a/src/submodules/NeumannBC/src/NeumannBC_Class@GetMethods.F90 b/src/submodules/NeumannBC/src/NeumannBC_Class@GetMethods.F90 index f3859271c..bab133d43 100644 --- a/src/submodules/NeumannBC/src/NeumannBC_Class@GetMethods.F90 +++ b/src/submodules/NeumannBC/src/NeumannBC_Class@GetMethods.F90 @@ -40,4 +40,12 @@ ans => nbc(nbcNo)%ptr END PROCEDURE bc_GetNeumannBCPointer +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetPrefix +ans = myprefix +END PROCEDURE bc_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/NeumannBC/src/NeumannBC_Class@IOMethods.F90 b/src/submodules/NeumannBC/src/NeumannBC_Class@IOMethods.F90 index b25cd1a5a..406c5001b 100644 --- a/src/submodules/NeumannBC/src/NeumannBC_Class@IOMethods.F90 +++ b/src/submodules/NeumannBC/src/NeumannBC_Class@IOMethods.F90 @@ -16,6 +16,104 @@ ! SUBMODULE(NeumannBC_Class) IOMethods +USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml1()" +TYPE(toml_table), POINTER :: node +TYPE(toml_array), POINTER :: array +INTEGER(I4B) :: origin, stat, tsize, ii, tsize1 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +tsize1 = SIZE(obj) + +array => NULL() +CALL toml_get(table, tomlName, array, origin=origin, & + & requested=.FALSE., stat=stat) + +IF (.NOT. ASSOCIATED(array)) THEN + IF (tsize1 .GT. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + ELSE + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + END IF + RETURN +END IF + +tsize = toml_len(array) +IF (tsize .NE. tsize1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The number of boundary condition '// & + & ' in the toml config is not same as the size of obj') + RETURN +END IF + +DO ii = 1, tsize + node => NULL() + CALL toml_get(array, ii, node) + IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: NeumannBC '//tostring(ii)// & + & ' cannot be read from the toml file.') + END IF + IF (.NOT. ASSOCIATED(obj(ii)%ptr)) ALLOCATE (obj(ii)%ptr) + CALL obj(ii)%ptr%ImportFromToml(table=node, dom=dom) +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +CALL NeumannBCImportFromToml(obj=obj, table=table, dom=dom, & + & tomlName=tomlName) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml2 END SUBMODULE IOMethods diff --git a/src/submodules/NitscheBC/src/NitscheBC_Class@ConstructorMethods.F90 b/src/submodules/NitscheBC/src/NitscheBC_Class@ConstructorMethods.F90 index bbc2ee44b..d4acac32a 100644 --- a/src/submodules/NitscheBC/src/NitscheBC_Class@ConstructorMethods.F90 +++ b/src/submodules/NitscheBC/src/NitscheBC_Class@ConstructorMethods.F90 @@ -20,47 +20,6 @@ IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_checkEssentialParam -CALL AbstractBCcheckEssentialParam(& -& obj=obj, & -& param=param, & -& prefix=myprefix) -END PROCEDURE bc_checkEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE setNitscheBCParam -CALL setAbstractBCParam(& -& param=param, & -& prefix=myprefix, & -& name=name, & -& idof=idof, & -& nodalValueType=nodalValueType, & -& useFunction=input(option=useFunction, default=.FALSE.), & -& isNormal=input(option=isNormal, default=.FALSE.), & -& useExternal=input(option=useExternal, default=.FALSE.), & -& isTangent=input(option=isTangent, default=.FALSE.) & -& ) -END PROCEDURE setNitscheBCParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE bc_Initiate -CALL AbstractBCInitiate(obj=obj, & -& param=param, & -& prefix=myprefix, & -& boundary=boundary, & -& dom=dom) -END PROCEDURE bc_Initiate - !---------------------------------------------------------------------------- ! Final !---------------------------------------------------------------------------- diff --git a/src/submodules/NitscheBC/src/NitscheBC_Class@GetMethods.F90 b/src/submodules/NitscheBC/src/NitscheBC_Class@GetMethods.F90 index 705f0af65..b2719e4c2 100644 --- a/src/submodules/NitscheBC/src/NitscheBC_Class@GetMethods.F90 +++ b/src/submodules/NitscheBC/src/NitscheBC_Class@GetMethods.F90 @@ -32,6 +32,10 @@ END IF END PROCEDURE bc_GetMinCellEntity +!---------------------------------------------------------------------------- +! GetMaxCellEntity +!---------------------------------------------------------------------------- + MODULE PROCEDURE bc_GetMaxCellEntity IF (ALLOCATED(obj%cellEntity)) THEN ans = UBOUND(obj%cellEntity, 1) - 1 @@ -40,7 +44,11 @@ END IF END PROCEDURE bc_GetMaxCellEntity -MODULE PROCEDURE bc_isCellEntityPresent +!---------------------------------------------------------------------------- +! IsCellEntityPresent +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_IsCellEntityPresent INTEGER(I4B) :: ii IF (ALLOCATED(obj%cellEntity)) THEN @@ -57,42 +65,42 @@ ELSE ans = .FALSE. END IF -END PROCEDURE bc_isCellEntityPresent +END PROCEDURE bc_IsCellEntityPresent !---------------------------------------------------------------------------- -! +! GetStartIndex !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_getStartIndex +MODULE PROCEDURE bc_GetStartIndex ans = obj%cellEntity(entityNum) -END PROCEDURE bc_getStartIndex +END PROCEDURE bc_GetStartIndex !---------------------------------------------------------------------------- -! +! GetEndIndex !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_getEndIndex +MODULE PROCEDURE bc_GetEndIndex ans = obj%cellEntity(entityNum + 1) - 1 -END PROCEDURE bc_getEndIndex +END PROCEDURE bc_GetEndIndex !---------------------------------------------------------------------------- -! +! GetCellElem !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_getCellElem +MODULE PROCEDURE bc_GetCellElem ans = obj%cellElem(entityNum) -END PROCEDURE bc_getCellElem +END PROCEDURE bc_GetCellElem !---------------------------------------------------------------------------- -! +! GetLocalFacetID !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_getLocalFacetID +MODULE PROCEDURE bc_GetLocalFacetID ans = obj%localFacetID(entityNum) -END PROCEDURE bc_getLocalFacetID +END PROCEDURE bc_GetLocalFacetID !---------------------------------------------------------------------------- -! GetNitscheBCPointer +! GetNitscheBCPointer !---------------------------------------------------------------------------- MODULE PROCEDURE bc_GetNitscheBCPointer @@ -113,4 +121,12 @@ END PROCEDURE bc_GetNitscheBCPointer +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetPrefix +ans = myprefix +END PROCEDURE bc_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/NitscheBC/src/NitscheBC_Class@IOMethods.F90 b/src/submodules/NitscheBC/src/NitscheBC_Class@IOMethods.F90 index 9405464ee..158d6fe56 100644 --- a/src/submodules/NitscheBC/src/NitscheBC_Class@IOMethods.F90 +++ b/src/submodules/NitscheBC/src/NitscheBC_Class@IOMethods.F90 @@ -16,6 +16,104 @@ ! SUBMODULE(NitscheBC_Class) IOMethods +USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml1()" +TYPE(toml_table), POINTER :: node +TYPE(toml_array), POINTER :: array +INTEGER(I4B) :: origin, stat, tsize, ii, tsize1 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +tsize1 = SIZE(obj) + +array => NULL() +CALL toml_get(table, tomlName, array, origin=origin, & + & requested=.FALSE., stat=stat) + +IF (.NOT. ASSOCIATED(array)) THEN + IF (tsize1 .GT. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + ELSE + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'In toml file :: cannot find ['//tomlName//"] table.") + END IF + RETURN +END IF + +tsize = toml_len(array) +IF (tsize .NE. tsize1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The number of boundary condition '// & + & ' in the toml config is not same as the size of obj') + RETURN +END IF + +DO ii = 1, tsize + node => NULL() + CALL toml_get(array, ii, node) + IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: NitscheBC '//tostring(ii)// & + & ' cannot be read from the toml file.') + END IF + IF (.NOT. ASSOCIATED(obj(ii)%ptr)) ALLOCATE (obj(ii)%ptr) + CALL obj(ii)%ptr%ImportFromToml(table=node, dom=dom) +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "bc_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +CALL NitscheBCImportFromToml(obj=obj, table=table, dom=dom, & + & tomlName=tomlName) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE bc_ImportFromToml2 END SUBMODULE IOMethods diff --git a/src/submodules/NitscheBC/src/NitscheBC_Class@SetMethods.F90 b/src/submodules/NitscheBC/src/NitscheBC_Class@SetMethods.F90 index 4607813f9..bebc0a21e 100644 --- a/src/submodules/NitscheBC/src/NitscheBC_Class@SetMethods.F90 +++ b/src/submodules/NitscheBC/src/NitscheBC_Class@SetMethods.F90 @@ -13,7 +13,6 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see -! SUBMODULE(NitscheBC_Class) SetMethods USE BaseMethod diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index dcd6a8c11..a14296b7a 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(STScalarField_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS @@ -25,33 +26,29 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetSTScalarFieldParam -INTEGER(I4B) :: ierr -ierr = param%Set(key=myprefix//"/name", VALUE=TRIM(name)) -ierr = param%Set(key=myprefix//"/timeCompo", VALUE=timeCompo) -ierr = param%Set(key=myprefix//"/engine", VALUE=TRIM(engine)) -IF (PRESENT(fieldType)) THEN - ierr = param%Set(key=myprefix//"/fieldType", VALUE=fieldType) -ELSE - ierr = param%Set(key=myprefix//"/fieldType", VALUE=FIELD_TYPE_NORMAL) -END IF - -IF (PRESENT(comm)) THEN - ierr = param%Set(key=myprefix//"/comm", VALUE=comm) -ELSE - ierr = param%Set(key=myprefix//"/comm", VALUE=0_I4B) -END IF - -IF (PRESENT(local_n)) THEN - ierr = param%Set(key=myprefix//"/local_n", VALUE=local_n) -ELSE - ierr = param%Set(key=myprefix//"/local_n", VALUE=0_I4B) -END IF - -IF (PRESENT(global_n)) THEN - ierr = param%Set(key=myprefix//"/global_n", VALUE=global_n) -ELSE - ierr = param%Set(key=myprefix//"/global_n", VALUE=0_I4B) -END IF +TYPE(ParameterList_), POINTER :: sublist + +CALL SetAbstractFieldParam( & + & param=param, & + & prefix=myprefix, & + & name=name, & + & engine=engine, & + & fieldType=fieldType, & + & comm=comm, & + & local_n=local_n, & + & global_n=global_n) + +sublist => NULL() +sublist => param%NewSubList(key=myprefix) + +CALL Set( & + & obj=sublist, & + & datatype=TypeIntI4B, & + & prefix=myprefix, & + & key="timeCompo", & + & VALUE=timeCompo) + +sublist => NULL() END PROCEDURE SetSTScalarFieldParam !---------------------------------------------------------------------------- @@ -59,30 +56,11 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE stsField_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "stsField_CheckEssentialParam" -IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/name should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/engine")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/engine should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/timeCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/timeCompo should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/comm")) THEN +CHARACTER(*), PARAMETER :: myName = "stsField_CheckEssentialParam()" +CALL AbstractFieldCheckEssentialParam(obj=obj, param=param, prefix=myprefix) +IF (.NOT. param%IsPresent(key=myprefix//"/timeCompo")) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & 'comm should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/global_n")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'global_n should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/local_n")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'local_n should be present in param') + & 'timeCompo should be present in param.') END IF END PROCEDURE stsField_CheckEssentialParam @@ -91,7 +69,60 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE stsField_Initiate1 -CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1" +CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1()" +TYPE(String) :: astr +INTEGER(I4B) :: nsd, tdof, ierr, timeCompo, tNodes +TYPE(ParameterList_), POINTER :: sublist + +! main +sublist => NULL() + +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF + +CALL obj%CheckEssentialParam(sublist) +CALL obj%DEALLOCATE() + +CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) +CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", VALUE=timeCompo) +tNodes = dom%GetTotalNodes() +tdof = tNodes * timeCompo + +CALL AbstractNodeFieldSetParam(obj=obj, & + & dof_tPhysicalVars=1_I4B, & + & dof_storageFMT=NODES_FMT, & + & dof_spaceCompo=[1_I4B], & + & dof_timeCompo=[timeCompo], & + & dof_tNodes=[tNodes], & + & dof_names_char=[astr%slice(1, 1)], & + & tSize=tdof) + +nsd = dom%GetNSD() + +CALL AbstractNodeFieldInitiate( & + & obj=obj, & + & param=param, & + & dom=dom, & + & prefix=myprefix) + +astr = "" +sublist => NULL() +END PROCEDURE stsField_Initiate1 + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stsField_Initiate1_old +CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1_old" INTEGER(I4B) :: ierr, storageFMT, tNodes(1), spaceCompo(1), & & timeCompo(1) CHARACTER(:), ALLOCATABLE :: char_var @@ -172,7 +203,7 @@ obj%isInitiated = .TRUE. IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE stsField_Initiate1 +END PROCEDURE stsField_Initiate1_old !---------------------------------------------------------------------------- ! Initiate diff --git a/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 index 4d7bb288f..ce6b7e306 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 @@ -22,11 +22,11 @@ CONTAINS !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get1 -CHARACTER(*), PARAMETER :: myName = "stsField_get1" +MODULE PROCEDURE stsField_Get1 +CHARACTER(*), PARAMETER :: myName = "stsField_Get1" LOGICAL(LGT) :: bool1, bool2 IF (.NOT. obj%isInitiated) THEN @@ -45,24 +45,24 @@ IF (bool1) THEN SELECT CASE (obj%fieldType) CASE (FIELD_TYPE_CONSTANT) - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%timeCompo), & & VALUE=VALUE, & & nodenum=[1]) CASE (FIELD_TYPE_NORMAL) - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%timeCompo), & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber([globalnode])) + & nodenum=obj%domain%GetLocalNodeNumber([globalnode])) END SELECT END IF IF (bool2) THEN - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & ivar=1, & @@ -70,124 +70,124 @@ & VALUE=VALUE) END IF -END PROCEDURE stsField_get1 +END PROCEDURE stsField_Get1 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get2 -CHARACTER(*), PARAMETER :: myName = "stsField_get2" +MODULE PROCEDURE stsField_Get2 +CHARACTER(*), PARAMETER :: myName = "stsField_Get2" IF (.NOT. obj%isInitiated) THEN CALL e%raiseError(modName//'::'//myName//" - "// & & 'STScalarField_::obj is not initiated') END IF -CALL getValue( & +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%timeCompo), & & VALUE=VALUE) -END PROCEDURE stsField_get2 +END PROCEDURE stsField_Get2 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get3 +MODULE PROCEDURE stsField_Get3 REAL(DFP), ALLOCATABLE :: v(:) -CALL getValue( & +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%timeCompo), & & VALUE=v, & - & nodenum=obj%domain%getLocalNodeNumber(globalnode)) + & nodenum=obj%domain%GetLocalNodeNumber(globalnode)) VALUE = RESHAPE(v, [obj%timeCompo, SIZE(globalnode)]) DEALLOCATE (v) -END PROCEDURE stsField_get3 +END PROCEDURE stsField_Get3 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get4 -CALL getValue( & +MODULE PROCEDURE stsField_Get4 +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & ivar=1, & & idof=timeCompo, & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber(globalnode)) -END PROCEDURE stsField_get4 + & nodenum=obj%domain%GetLocalNodeNumber(globalnode)) +END PROCEDURE stsField_Get4 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get5 -CALL getValue( & +MODULE PROCEDURE stsField_Get5 +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & ivar=1, & & idof=timeCompo, & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber(globalnode)) -END PROCEDURE stsField_get5 + & nodenum=obj%domain%GetLocalNodeNumber(globalnode)) +END PROCEDURE stsField_Get5 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get6 +MODULE PROCEDURE stsField_Get6 INTEGER(I4B) :: globalnode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalnode(jj) = ii END DO -CALL obj%get(globalnode=globalnode, VALUE=VALUE) -END PROCEDURE stsField_get6 +CALL obj%Get(globalnode=globalnode, VALUE=VALUE) +END PROCEDURE stsField_Get6 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get7 +MODULE PROCEDURE stsField_Get7 INTEGER(I4B) :: globalnode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalnode(jj) = ii END DO -CALL obj%get(globalnode=globalnode, VALUE=VALUE, timeCompo=timeCompo) -END PROCEDURE stsField_get7 +CALL obj%Get(globalnode=globalnode, VALUE=VALUE, timeCompo=timeCompo) +END PROCEDURE stsField_Get7 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get8 +MODULE PROCEDURE stsField_Get8 REAL(DFP), ALLOCATABLE :: v(:) -CALL getValue( & +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & VALUE=v, & & idof=arange(1, obj%timeCompo), & - & nodenum=obj%domain%getLocalNodeNumber(globalnode)) + & nodenum=obj%domain%GetLocalNodeNumber(globalnode)) VALUE = NodalVariable( & & RESHAPE(v, [obj%timeCompo, SIZE(globalnode)]), & & TypeFEVariableScalar, & & TypeFEVariableSpaceTime) DEALLOCATE (v) -END PROCEDURE stsField_get8 +END PROCEDURE stsField_Get8 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get9 -CHARACTER(*), PARAMETER :: myName = "stsField_get9" +MODULE PROCEDURE stsField_Get9 +CHARACTER(*), PARAMETER :: myName = "stsField_Get9" INTEGER(I4B) :: n n = (obj%dof.timecomponents.1) IF (timecompo .GT. n) & @@ -207,26 +207,26 @@ CALL e%raiseError(modName//'::'//myName//' - '// & & 'No case found for type of value') END SELECT -END PROCEDURE stsField_get9 +END PROCEDURE stsField_Get9 !---------------------------------------------------------------------------- -! getPointerOfComponent +! GetPointerOfComponent !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_getPointerOfComponent -CHARACTER(*), PARAMETER :: myName = "stsField_getPointerOfComponent" +MODULE PROCEDURE stsField_GetPointerOfComponent +CHARACTER(*), PARAMETER :: myName = "stsField_GetPointerOfComponent" IF (timeCompo .GT. obj%timeCompo) & & CALL e%raiseError(modName//'::'//myName//" - "// & & 'given timeCompo should be less than or equal to obj%timeCompo') -ans => getPointer(obj=obj%realvec, dofobj=obj%dof, idof=timeCompo) -END PROCEDURE stsField_getPointerOfComponent +ans => GetPointer(obj=obj%realvec, dofobj=obj%dof, idof=timeCompo) +END PROCEDURE stsField_GetPointerOfComponent !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_get10 -CHARACTER(*), PARAMETER :: myName = "stsField_get10" +MODULE PROCEDURE stsField_Get10 +CHARACTER(*), PARAMETER :: myName = "stsField_Get10" INTEGER(I4B) :: tsize INTEGER(I4B) :: tsize_value INTEGER(I4B) :: ii @@ -266,6 +266,14 @@ CALL VALUE%SetSingle(VALUE=avar, indx=indx2) END DO -END PROCEDURE stsField_get10 +END PROCEDURE stsField_Get10 + +!---------------------------------------------------------------------------- +! GetTimeCompo +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stsField_GetTimeCompo + ans = obj%timeCompo +END PROCEDURE stsField_GetTimeCompo END SUBMODULE GetMethods diff --git a/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@SetMethods.F90 b/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@SetMethods.F90 index 6233d15a1..b7f8e4c64 100644 --- a/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@SetMethods.F90 +++ b/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@SetMethods.F90 @@ -26,7 +26,7 @@ ! SetSingle !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_setSingle +MODULE PROCEDURE stsField_SetSingle #include "lisf.h" INTEGER(I4B) :: i, ierr REAL(DFP) :: value0 @@ -59,13 +59,13 @@ CALL CHKERR(ierr) END IF -END PROCEDURE stsField_setSingle +END PROCEDURE stsField_SetSingle !---------------------------------------------------------------------------- ! SetMultiple !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_setMultiple +MODULE PROCEDURE stsField_SetMultiple #include "lisf.h" INTEGER(I4B) :: i(SIZE(indx)), ierr, n REAL(DFP) :: value0(SIZE(VALUE)) @@ -96,13 +96,13 @@ & ) CALL CHKERR(ierr) END IF -END PROCEDURE stsField_setMultiple +END PROCEDURE stsField_SetMultiple !---------------------------------------------------------------------------- ! SetAll !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_setAll +MODULE PROCEDURE stsField_SetAll #include "lisf.h" INTEGER(I4B) :: ierr, ii, n REAL(DFP) :: value0 @@ -129,36 +129,39 @@ & ) CALL CHKERR(ierr) END IF -END PROCEDURE stsField_setAll +END PROCEDURE stsField_SetAll !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set1 -CHARACTER(*), PARAMETER :: myName = "stsField_set1" +MODULE PROCEDURE stsField_Set1 +CHARACTER(*), PARAMETER :: myName = "stsField_Set1" INTEGER(I4B) :: localNode INTEGER(I4B) :: tsize -INTEGER(I4B) :: indx(obj%timeCompo) -INTEGER(I4B) :: ierr +INTEGER(I4B), ALLOCATABLE :: indx(:) +INTEGER(I4B) :: ierr, timeCompo + +timeCompo = STScalarFieldGetTimeCompo(obj) +CALL Reallocate(indx, timeCompo) CALL lis_vector_is_null(obj%lis_ptr, ierr) CALL CHKERR(ierr) -IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & +IF (.NOT. obj%IsInitiated .OR. ierr .EQ. LIS_TRUE) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF -IF (SIZE(VALUE) .NE. obj%timeCompo) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & +IF (SIZE(VALUE) .NE. timeCompo) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Size of value should be equal to obj%timeCompo') END IF -localNode = obj%domain%getLocalNodeNumber(globalNode) +localNode = obj%domain%GetLocalNodeNumber(globalNode) IF (localNode .EQ. 0_I4B) THEN - CALL e%raiseError(modName//'::'//myName//" - " & + CALL e%RaiseError(modName//'::'//myName//" - " & & //'globalNode :: '//TRIM(str(globalNode, .TRUE.)) & & //" is out of bound for the domain.") END IF @@ -171,33 +174,37 @@ & scale=scale, & & addContribution=addContribution) -END PROCEDURE stsField_set1 +IF (ALLOCATED(indx)) DEALLOCATE (indx) +END PROCEDURE stsField_Set1 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set2 -CHARACTER(*), PARAMETER :: myName = "stsField_set2" +MODULE PROCEDURE stsField_Set2 +CHARACTER(*), PARAMETER :: myName = "stsField_Set2" INTEGER(I4B) :: ii INTEGER(I4B) :: tsize -INTEGER(I4B) :: indx(obj%timeCompo) -INTEGER(I4B) :: ierr +INTEGER(I4B), ALLOCATABLE :: indx(:) +INTEGER(I4B) :: ierr, timeCompo + +timeCompo = STScalarFieldGetTimeCompo(obj) +CALL Reallocate(indx, timeCompo) CALL lis_vector_is_null(obj%lis_ptr, ierr) CALL CHKERR(ierr) -IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & +IF (.NOT. obj%IsInitiated .OR. ierr .EQ. LIS_TRUE) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either ScalarField object is not initiated'// & & " or, lis_ptr is not available") END IF IF (SIZE(VALUE) .NE. obj%timeCompo) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'size(value) should be same as obj%timeCompo') END IF -tsize = obj%domain%getTotalNodes() +tsize = obj%domain%GetTotalNodes() DO ii = 1, tsize indx = GetIndex(obj=obj%dof, nodenum=ii) @@ -208,33 +215,37 @@ & addContribution=addContribution) END DO -END PROCEDURE stsField_set2 +IF (ALLOCATED(indx)) DEALLOCATE (indx) + +END PROCEDURE stsField_Set2 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set3 -CHARACTER(*), PARAMETER :: myName = "stsField_set3" +MODULE PROCEDURE stsField_Set3 +CHARACTER(*), PARAMETER :: myName = "stsField_Set3" INTEGER(I4B) :: indx INTEGER(I4B) :: tsize INTEGER(I4B) :: ii -INTEGER(I4B) :: ierr +INTEGER(I4B) :: ierr, timeCompo0 CALL lis_vector_is_null(obj%lis_ptr, ierr) CALL CHKERR(ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF -IF (timeCompo .GT. obj%timeCompo) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & +timeCompo0 = STScalarFieldGetTimeCompo(obj) + +IF (timeCompo .GT. timeCompo0) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'given timeCompo should be less than or equal to obj%timeCompo') END IF -tsize = obj%domain%getTotalNodes() +tsize = obj%domain%GetTotalNodes() DO ii = 1, tsize indx = GetNodeLoc(obj=obj%dof, nodenum=ii, idof=timeCompo) @@ -245,39 +256,41 @@ & addContribution=addContribution) END DO -END PROCEDURE stsField_set3 +END PROCEDURE stsField_Set3 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set4 -CHARACTER(*), PARAMETER :: myName = "stsField_set4" +MODULE PROCEDURE stsField_Set4 +CHARACTER(*), PARAMETER :: myName = "stsField_Set4" INTEGER(I4B) :: ii, tnodes, aa, jj -INTEGER(I4B) :: ierr +INTEGER(I4B) :: ierr, timeCompo CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF +timeCompo = STScalarFieldGetTimeCompo(obj) + IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This subroutine is not callable for constant STScalar field') END IF tnodes = obj%domain%getTotalNodes() IF ( & - & SIZE(VALUE, 1) .NE. obj%timeCompo & + & SIZE(VALUE, 1) .NE. timeCompo & & .OR. SIZE(VALUE, 2) .NE. tnodes) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The shape of value should be [ ' & - & //tostring(obj%timeCompo) & + & //tostring(timeCompo) & & //', ' & & //tostring(tnodes) & & //' ]') @@ -286,7 +299,7 @@ aa = 0 DO jj = 1, tnodes - DO ii = 1, obj%timeCompo + DO ii = 1, timeCompo aa = aa + 1 CALL obj%SetSingle(& & indx=aa, & @@ -296,39 +309,41 @@ END DO END DO -END PROCEDURE stsField_set4 +END PROCEDURE stsField_Set4 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set5 -CHARACTER(*), PARAMETER :: myName = "stsField_set5" +MODULE PROCEDURE stsField_Set5 +CHARACTER(*), PARAMETER :: myName = "stsField_Set5" INTEGER(I4B) :: ii INTEGER(I4B) :: indx INTEGER(I4B) :: ierr -INTEGER(I4B) :: tsize +INTEGER(I4B) :: tsize, timeCompo0 CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF -IF (timeCompo .GT. obj%timeCompo) & - & CALL e%raiseError(modName//'::'//myName//" - "// & +timeCompo0 = STScalarFieldGetTimeCompo(obj) + +IF (timeCompo .GT. timeCompo0) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'given timeCompo should be less than or equal to obj%timeCompo') IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This subroutine is not callable for constant STScalar field') tsize = SIZE(VALUE) IF (tsize .NE. obj%domain%getTotalNodes()) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Size of value should be equal to the total number of nodes') DO ii = 1, tsize @@ -340,60 +355,62 @@ & addContribution=addContribution) END DO -END PROCEDURE stsField_set5 +END PROCEDURE stsField_Set5 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set6 +MODULE PROCEDURE stsField_Set6 REAL(DFP), POINTER :: vecPointer(:) -CHARACTER(*), PARAMETER :: myName = "stsField_set5" +CHARACTER(*), PARAMETER :: myName = "stsField_Set5" INTEGER(I4B) :: ierr INTEGER(I4B) :: tsize1 INTEGER(I4B) :: tsize INTEGER(I4B) :: ii INTEGER(I4B) :: jj -INTEGER(I4B) :: indx +INTEGER(I4B) :: indx, timeCompo0 REAL(DFP) :: avar CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE & & .OR. .NOT. VALUE%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::object is not initiated'// & & ', or, ScalarField::value is not initiated'// & & ", or, obj%lis_ptr is not available") END IF -IF (timeCompo .GT. obj%timeCompo) & - & CALL e%raiseError(modName//'::'//myName//" - "// & +timeCompo0 = STScalarFieldGetTimeCompo(obj) + +IF (timeCompo .GT. timeCompo0) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'given timeCompo should be less than or equal to obj%timeCompo') IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This subroutine is not callable for constant STScalar field') -tsize = obj%domain%getTotalNodes() -tsize1 = VALUE%domain%getTotalNodes() +tsize = obj%domain%GetTotalNodes() +tsize1 = VALUE%domain%GetTotalNodes() IF (tsize .NE. tsize1) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Size of value should be equal to the total number of nodes') END IF SELECT TYPE (VALUE) -TYPE is (ScalarField_) +TYPE IS (ScalarField_) IF (VALUE%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - vecPointer => VALUE%getPointer() - CALL obj%set(VALUE=vecPointer(1), timeCompo=timeCompo, & + vecPointer => VALUE%GetPointer() + CALL obj%Set(VALUE=vecPointer(1), timeCompo=timeCompo, & & scale=scale, addContribution=addContribution) vecPointer => NULL() ELSE - vecPointer => VALUE%getPointer() - CALL obj%set(VALUE=vecPointer, timeCompo=timeCompo, & + vecPointer => VALUE%GetPointer() + CALL obj%Set(VALUE=vecPointer, timeCompo=timeCompo, & & scale=scale, addContribution=addContribution) vecPointer => NULL() END IF @@ -403,14 +420,14 @@ CALL lis_vector_is_null(VALUE%lis_ptr, ierr) IF (ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & "ScalarFieldLis_::value%lis_ptr is not available") END IF IF (VALUE%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN CALL VALUE%get(VALUE=avar, globalNode=1) - CALL obj%set( & + CALL obj%Set( & & VALUE=avar, & & timeCompo=timeCompo, & & scale=scale, & @@ -427,7 +444,7 @@ ! CALL Display(avar, "avar = ") indx = GetNodeLoc(obj=obj%dof, nodenum=ii, idof=timeCompo) - CALL obj%setSingle( & + CALL obj%SetSingle( & & VALUE=avar, & & indx=indx, & & scale=scale, & @@ -440,55 +457,57 @@ END IF CLASS DEFAULT - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'No case found for the type of Value') END SELECT -END PROCEDURE stsField_set6 +END PROCEDURE stsField_Set6 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set7 +MODULE PROCEDURE stsField_Set7 REAL(DFP) :: val(SIZE(VALUE), SIZE(globalNode)) INTEGER(I4B) :: ii DO ii = 1, SIZE(globalNode) val(:, ii) = VALUE(:) END DO -CALL obj%set( & +CALL obj%Set( & & VALUE=val, & & globalNode=globalNode, & & scale=scale, & & addContribution=addContribution) -END PROCEDURE stsField_set7 +END PROCEDURE stsField_Set7 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set8 -CHARACTER(*), PARAMETER :: myName = "stsField_set8" +MODULE PROCEDURE stsField_Set8 +CHARACTER(*), PARAMETER :: myName = "stsField_Set8" INTEGER(I4B) :: localNode(SIZE(globalNode)) REAL(DFP) :: val(SIZE(VALUE)) INTEGER(I4B) :: indx(SIZE(VALUE)) -INTEGER(I4B) :: ierr +INTEGER(I4B) :: ierr, timeCompo0 CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This routine should not be called for constant STScalar field') -IF (SIZE(VALUE, 1) .NE. obj%timeCompo .OR. & +timeCompo0 = STScalarFieldGetTimeCompo(obj) + +IF (SIZE(VALUE, 1) .NE. timeCompo0 .OR. & & SIZE(VALUE, 2) .NE. SIZE(globalNode)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'SIZE( value, 1 ) not equal to timeCompo'// & & 'or SIZE( value, 2 ) not equal to'// & & ' the SIZE(globalNode)') @@ -497,7 +516,7 @@ localNode = obj%domain%getLocalNodeNumber(globalNode) IF (ANY(localNode .EQ. 0_I4B)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Some of the globalNode are out of bound') END IF @@ -507,7 +526,7 @@ & nodenum=localNode, & & ivar=1_I4B, & & spaceCompo=1_I4B, & -& timeCompo=arange(1, obj%timeCompo)) +& timeCompo=arange(1, timeCompo0)) CALL obj%SetMultiple(& & VALUE=val, & @@ -515,42 +534,44 @@ & scale=scale, & & addContribution=addContribution) -END PROCEDURE stsField_set8 +END PROCEDURE stsField_Set8 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set9 -CHARACTER(*), PARAMETER :: myName = "stsField_set9" +MODULE PROCEDURE stsField_Set9 +CHARACTER(*), PARAMETER :: myName = "stsField_Set9" INTEGER(I4B) :: localNode(SIZE(globalNode)) INTEGER(I4B) :: indx(SIZE(globalNode)) -INTEGER(I4B) :: ierr +INTEGER(I4B) :: ierr, timeCompo0 CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF -IF (timeCompo .GT. obj%timeCompo) & - & CALL e%raiseError(modName//'::'//myName//" - "// & +timeCompo0 = STScalarFieldGetTimeCompo(obj) + +IF (timeCompo .GT. timeCompo0) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'given timeCompo should be less than or equal to obj%timeCompo') IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This subroutine is not callable for constant STScalar field') IF (SIZE(VALUE) .NE. SIZE(globalNode)) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Size of value should be equal to size of globalNode') localNode = obj%domain%getLocalNodeNumber(globalNode) IF (ANY(localNode .EQ. 0_I4B)) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Some of the global node num are out of bound') indx = GetNodeLoc(& @@ -567,38 +588,41 @@ & scale=scale, & & addContribution=addContribution) -END PROCEDURE stsField_set9 +END PROCEDURE stsField_Set9 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set10 -CHARACTER(*), PARAMETER :: myName = "stsField_set10" +MODULE PROCEDURE stsField_Set10 +CHARACTER(*), PARAMETER :: myName = "stsField_Set10" INTEGER(I4B) :: indx INTEGER(I4B) :: localNode INTEGER(I4B) :: ierr +INTEGER(I4B) :: timeCompo0 CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF -IF (timeCompo .GT. obj%timeCompo) & - & CALL e%raiseError(modName//'::'//myName//" - "// & +timeCompo0 = STScalarFieldGetTimeCompo(obj) + +IF (timeCompo .GT. timeCompo0) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'given timeCompo should be less than or equal to obj%timeCompo') IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This subroutine is not callable for constant STScalar field') -localNode = obj%domain%getLocalNodeNumber(globalNode) +localNode = obj%domain%GetLocalNodeNumber(globalNode) IF (localNode .EQ. 0_I4B) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The given global node num are out of bound') indx = getNodeLoc( & @@ -608,68 +632,68 @@ & timeCompo=timeCompo, & & nodenum=localNode) -CALL obj%setSingle(& +CALL obj%SetSingle(& & indx=indx, & & VALUE=VALUE, & & scale=scale, & & addContribution=addContribution) -END PROCEDURE stsField_set10 +END PROCEDURE stsField_Set10 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set11 -CHARACTER(*), PARAMETER :: myName = "stsField_set11" +MODULE PROCEDURE stsField_Set11 +CHARACTER(*), PARAMETER :: myName = "stsField_Set11" INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%set(globalNode=globalNode, VALUE=VALUE, & +CALL obj%Set(globalNode=globalNode, VALUE=VALUE, & & scale=scale, addContribution=addContribution) -END PROCEDURE stsField_set11 +END PROCEDURE stsField_Set11 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set12 -CHARACTER(*), PARAMETER :: myName = "stsField_set12" +MODULE PROCEDURE stsField_Set12 +CHARACTER(*), PARAMETER :: myName = "stsField_Set12" INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%set( & +CALL obj%Set( & & globalNode=globalNode, & & VALUE=VALUE, & & scale=scale, & & addContribution=addContribution) -END PROCEDURE stsField_set12 +END PROCEDURE stsField_Set12 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set13 -CHARACTER(*), PARAMETER :: myName = "stsField_set13" +MODULE PROCEDURE stsField_Set13 +CHARACTER(*), PARAMETER :: myName = "stsField_Set13" IF (.NOT. obj%isInitiated) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Scalar field object is not initiated') IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & 'This routine should not be called for constant STScalar field') SELECT CASE (VALUE%vartype) CASE (SpaceTime) - CALL obj%set( & + CALL obj%Set( & & VALUE=GET(VALUE, TypeFEVariableScalar, TypeFEVariableSpaceTime), & & globalNode=globalNode, & & scale=scale, & @@ -677,31 +701,31 @@ CASE DEFAULT - CALL e%raiseError(modName//'::'//myName//' - '// & + CALL e%RaiseError(modName//'::'//myName//' - '// & & 'No case found for Value%vartype') END SELECT -END PROCEDURE stsField_set13 +END PROCEDURE stsField_Set13 !---------------------------------------------------------------------------- -! set +! Set !---------------------------------------------------------------------------- -MODULE PROCEDURE stsField_set14 -CHARACTER(*), PARAMETER :: myName = "stsField_set14" +MODULE PROCEDURE stsField_Set14 +CHARACTER(*), PARAMETER :: myName = "stsField_Set14" INTEGER(I4B) :: ierr CALL lis_vector_is_null(obj%lis_ptr, ierr) IF (.NOT. obj%isInitiated .OR. ierr .EQ. LIS_TRUE) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Either STScalarFieldLis_::obj is not initiated'// & & " or, obj%lis_ptr is not available") END IF -CALL obj%setAll(VALUE=VALUE, scale=scale, addContribution=addContribution) +CALL obj%SetAll(VALUE=VALUE, scale=scale, addContribution=addContribution) -END PROCEDURE stsField_set14 +END PROCEDURE stsField_Set14 !---------------------------------------------------------------------------- ! diff --git a/src/submodules/STScalarMeshField/src/STScalarMeshField_Class@ConstructorMethods.F90 b/src/submodules/STScalarMeshField/src/STScalarMeshField_Class@ConstructorMethods.F90 index 8c3a31b98..bb8e2331a 100644 --- a/src/submodules/STScalarMeshField/src/STScalarMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarMeshField/src/STScalarMeshField_Class@ConstructorMethods.F90 @@ -56,7 +56,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_CheckEssentialParam -CALL AbstractFieldCheckEssentialParam( & +CALL AbstractMeshFieldCheckEssentialParam( & & obj=obj, & & prefix="STScalarMeshField", & & param=param) diff --git a/src/submodules/STTensorMeshField/src/STTensorMeshField_Class@ConstructorMethods.F90 b/src/submodules/STTensorMeshField/src/STTensorMeshField_Class@ConstructorMethods.F90 index de733d555..cea4f136c 100644 --- a/src/submodules/STTensorMeshField/src/STTensorMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/STTensorMeshField/src/STTensorMeshField_Class@ConstructorMethods.F90 @@ -54,7 +54,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_CheckEssentialParam -CALL AbstractFieldCheckEssentialParam( & +CALL AbstractMeshFieldCheckEssentialParam( & & obj=obj, & & prefix="STTensorMeshField", & & param=param) diff --git a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 index c5724de82..980235baa 100644 --- a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(STVectorField_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS @@ -25,34 +26,37 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetSTVectorFieldParam -INTEGER(I4B) :: ierr -ierr = param%Set(key=myprefix//"/name", VALUE=TRIM(name)) -ierr = param%Set(key=myprefix//"/engine", VALUE=TRIM(engine)) -ierr = param%Set(key=myprefix//"/spaceCompo", VALUE=spaceCompo) -ierr = param%Set(key=myprefix//"/timeCompo", VALUE=timeCompo) -IF (PRESENT(fieldType)) THEN - ierr = param%Set(key=myprefix//"/fieldType", VALUE=fieldType) -ELSE - ierr = param%Set(key=myprefix//"/fieldType", VALUE=FIELD_TYPE_NORMAL) -END IF - -IF (PRESENT(comm)) THEN - ierr = param%Set(key=myprefix//"/comm", VALUE=comm) -ELSE - ierr = param%Set(key=myprefix//"/comm", VALUE=0_I4B) -END IF - -IF (PRESENT(local_n)) THEN - ierr = param%Set(key=myprefix//"/local_n", VALUE=local_n) -ELSE - ierr = param%Set(key=myprefix//"/local_n", VALUE=0_I4B) -END IF +TYPE(ParameterList_), POINTER :: sublist + +CALL SetAbstractFieldParam( & + & param=param, & + & prefix=myprefix, & + & name=name, & + & engine=engine, & + & fieldType=fieldType, & + & comm=comm, & + & local_n=local_n, & + & global_n=global_n) + +sublist => NULL() +sublist => param%NewSubList(key=myprefix) + +CALL Set( & + & obj=sublist, & + & datatype=TypeIntI4B, & + & prefix=myprefix, & + & key="spaceCompo", & + & VALUE=spaceCompo) + +CALL Set( & + & obj=sublist, & + & datatype=TypeIntI4B, & + & prefix=myprefix, & + & key="timeCompo", & + & VALUE=timeCompo) + +sublist => NULL() -IF (PRESENT(global_n)) THEN - ierr = param%Set(key=myprefix//"/global_n", VALUE=global_n) -ELSE - ierr = param%Set(key=myprefix//"/global_n", VALUE=0_I4B) -END IF END PROCEDURE SetSTVectorFieldParam !---------------------------------------------------------------------------- @@ -60,42 +64,77 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE stvField_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "stvField_CheckEssentialParam" -IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/name should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/engine")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/engine should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/spaceCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/spaceCompo should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/timeCompo")) THEN +CHARACTER(*), PARAMETER :: myName = "stvField_checkEssentialParam" +CALL AbstractFieldCheckEssentialParam(obj=obj, param=param, prefix=myprefix) +IF (.NOT. param%IsPresent(key=myprefix//"/spaceCompo")) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/timeCompo should be present in param') + & 'spaceCompo should be present in param.') END IF -IF (.NOT. param%isPresent(key=myprefix//"/comm")) THEN +IF (.NOT. param%IsPresent(key=myprefix//"/timeCompo")) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & 'comm should be present in param') + & 'timeCompo should be present in param.') END IF -IF (.NOT. param%isPresent(key=myprefix//"/global_n")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'global_n should be present in param') +END PROCEDURE stvField_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stvField_Initiate1 +CHARACTER(*), PARAMETER :: myName = "stvField_Initiate1()" +TYPE(String) :: astr +INTEGER(I4B) :: nsd, tdof, ierr, spaceCompo, tNodes, timeCompo +TYPE(ParameterList_), POINTER :: sublist + +! main +sublist => NULL() + +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') END IF -IF (.NOT. param%isPresent(key=myprefix//"/local_n")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'local_n should be present in param') + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') END IF -END PROCEDURE stvField_CheckEssentialParam + +CALL obj%CheckEssentialParam(sublist) +CALL obj%DEALLOCATE() + +CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) +CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", VALUE=spaceCompo) +CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", VALUE=timeCompo) +tNodes = dom%GetTotalNodes() +tdof = tNodes * spaceCompo * timeCompo + +CALL AbstractNodeFieldSetParam(obj=obj, & + & dof_tPhysicalVars=1_I4B, & + & dof_storageFMT=NODES_FMT, & + & dof_spaceCompo=[spaceCompo], & + & dof_timeCompo=[timeCompo], & + & dof_tNodes=[tNodes], & + & dof_names_char=[astr%slice(1, 1)], & + & tSize=tdof) + +nsd = dom%GetNSD() + +CALL AbstractNodeFieldInitiate( & + & obj=obj, & + & param=param, & + & dom=dom, & + & prefix=myprefix) + +astr = "" +sublist => NULL() +END PROCEDURE stvField_Initiate1 !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_Initiate1 +MODULE PROCEDURE stvField_Initiate1_old CHARACTER(*), PARAMETER :: myName = "stvField_Initiate1" INTEGER(I4B) :: ierr, storageFMT, tNodes(1), spaceCompo(1), & & timeCompo(1) @@ -180,7 +219,7 @@ obj%isInitiated = .TRUE. IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE stvField_Initiate1 +END PROCEDURE stvField_Initiate1_old !---------------------------------------------------------------------------- ! Initiate diff --git a/src/submodules/STVectorMeshField/src/STVectorMeshField_Class@ConstructorMethods.F90 b/src/submodules/STVectorMeshField/src/STVectorMeshField_Class@ConstructorMethods.F90 index 918043afb..d0f68dc52 100644 --- a/src/submodules/STVectorMeshField/src/STVectorMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/STVectorMeshField/src/STVectorMeshField_Class@ConstructorMethods.F90 @@ -56,7 +56,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_CheckEssentialParam -CALL AbstractFieldCheckEssentialParam( & +CALL AbstractMeshFieldCheckEssentialParam( & & obj=obj, & & prefix="STVectorMeshField", & & param=param) diff --git a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 index 783327b03..b039ccbab 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(ScalarField_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS @@ -25,33 +26,15 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetScalarFieldParam -INTEGER(I4B) :: ierr -ierr = param%Set(key=myprefix//"/name", VALUE=name) -ierr = param%Set(key=myprefix//"/engine", VALUE=engine) -IF (PRESENT(fieldType)) THEN - ierr = param%Set(key=myprefix//"/fieldType", VALUE=fieldType) -ELSE - ierr = param%Set(key=myprefix//"/fieldType", VALUE=FIELD_TYPE_NORMAL) -END IF - -IF (PRESENT(comm)) THEN - ierr = param%Set(key=myprefix//"/comm", VALUE=comm) -ELSE - ierr = param%Set(key=myprefix//"/comm", VALUE=0_I4B) -END IF - -IF (PRESENT(local_n)) THEN - ierr = param%Set(key=myprefix//"/local_n", VALUE=local_n) -ELSE - ierr = param%Set(key=myprefix//"/local_n", VALUE=0_I4B) -END IF - -IF (PRESENT(global_n)) THEN - ierr = param%Set(key=myprefix//"/global_n", VALUE=global_n) -ELSE - ierr = param%Set(key=myprefix//"/global_n", VALUE=0_I4B) -END IF - +CALL SetAbstractFieldParam( & + & param=param, & + & prefix=myprefix, & + & name=name, & + & engine=engine, & + & fieldType=fieldType, & + & comm=comm, & + & local_n=local_n, & + & global_n=global_n) END PROCEDURE SetScalarFieldParam !---------------------------------------------------------------------------- @@ -59,38 +42,66 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE sField_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "sField_CheckEssentialParam" -IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'names should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/engine")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'engine should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/fieldType")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'fieldType should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/comm")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'comm should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/global_n")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'global_n should be present in param') +CALL AbstractFieldCheckEssentialParam(obj=obj, param=param, prefix=myprefix) +END PROCEDURE sField_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE sField_Initiate1 +CHARACTER(*), PARAMETER :: myName = "sField_Initiate1()" +TYPE(String) :: astr +INTEGER(I4B) :: nsd, tdof, ierr, tNodes +TYPE(ParameterList_), POINTER :: sublist + +! main +sublist => NULL() + +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B ) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') END IF -IF (.NOT. param%isPresent(key=myprefix//"/local_n")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'local_n should be present in param') + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') END IF -END PROCEDURE sField_CheckEssentialParam + +CALL obj%CheckEssentialParam(sublist) + +CALL obj%DEALLOCATE() +CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) +tNodes = dom%GetTotalNodes() +tdof = tNodes + +CALL AbstractNodeFieldSetParam(obj=obj, & + & dof_tPhysicalVars=1_I4B, & + & dof_storageFMT=NODES_FMT, & + & dof_spaceCompo=[1_I4B], & + & dof_timeCompo=[1_I4B], & + & dof_tNodes=[tNodes], & + & dof_names_char=[astr%slice(1, 1)], & + & tSize=tdof) + +nsd = dom%GetNSD() + +CALL AbstractNodeFieldInitiate( & + & obj=obj, & + & param=param, & + & dom=dom, & + & prefix=myprefix) + +astr = "" +sublist => NULL() +END PROCEDURE sField_Initiate1 !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_Initiate1 +MODULE PROCEDURE sField_Initiate_old CHARACTER(*), PARAMETER :: myName = "sField_Initiate1" INTEGER(I4B) :: ierr, storageFMT INTEGER(I4B) :: tNodes(1), spaceCompo(1), timeCompo(1) @@ -98,7 +109,7 @@ CHARACTER(1) :: names_char(1) ! main program -CALL obj%Deallocate() +CALL obj%DEALLOCATE() CALL obj%CheckEssentialParam(param) ! engine @@ -166,7 +177,7 @@ IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE sField_Initiate1 +END PROCEDURE sField_Initiate_old !---------------------------------------------------------------------------- ! Final @@ -176,6 +187,14 @@ CALL obj%DEALLOCATE() END PROCEDURE sField_Final +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE sField_Deallocate +CALL AbstractNodeFieldDeallocate(obj) +END PROCEDURE sField_Deallocate + !---------------------------------------------------------------------------- ! ScalarField !---------------------------------------------------------------------------- diff --git a/src/submodules/ScalarMeshField/src/ScalarMeshField_Class@ConstructorMethods.F90 b/src/submodules/ScalarMeshField/src/ScalarMeshField_Class@ConstructorMethods.F90 index 86d47547a..f0ce16a1a 100644 --- a/src/submodules/ScalarMeshField/src/ScalarMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/ScalarMeshField/src/ScalarMeshField_Class@ConstructorMethods.F90 @@ -56,7 +56,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_CheckEssentialParam -CALL AbstractFieldCheckEssentialParam( & +CALL AbstractMeshFieldCheckEssentialParam( & & obj=obj, & & prefix="ScalarMeshField", & & param=param) diff --git a/src/submodules/TensorMeshField/src/TensorMeshField_Class@ConstructorMethods.F90 b/src/submodules/TensorMeshField/src/TensorMeshField_Class@ConstructorMethods.F90 index 044c8baca..04d23fac7 100644 --- a/src/submodules/TensorMeshField/src/TensorMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/TensorMeshField/src/TensorMeshField_Class@ConstructorMethods.F90 @@ -54,7 +54,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_CheckEssentialParam -CALL AbstractFieldCheckEssentialParam( & +CALL AbstractMeshFieldCheckEssentialParam( & & obj=obj, & & prefix=myPrefix, & & param=param) diff --git a/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 b/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 index 12d92b0f6..b37f968eb 100644 --- a/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 +++ b/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 @@ -29,65 +29,60 @@ CHARACTER(*), PARAMETER :: myName = 'txt_read_Line' CHARACTER(maxStrLen) :: buffer INTEGER(I4B) :: buffer_size, eioerr, ioerr -! + ioerr = 0 val = "" -! + IF (obj%isOpen() .AND. .NOT. obj%isEOF()) THEN - ! + DO WHILE (ioerr .NE. IOSTAT_EOR .AND. ioerr .NE. IOSTAT_END) - ! + ! Repeatedly read chunks of current input ! file line into buffer - ! READ ( & & UNIT=obj%getUnitNo(), & & FMT='(a)', & & SIZE=buffer_size, & & ADVANCE='NO', & & IOSTAT=ioerr) buffer - ! + IF (ioerr .EQ. IOSTAT_END) THEN - ! ! end of file - ! CALL obj%setEOFstat(.TRUE.) - ! ! Done reading line. Append last buffer to line. - ! + ELSEIF (ioerr .EQ. IOSTAT_EOR) THEN - ! val = val//TRIM(buffer) - ! + IF (obj%echostat) THEN - ! + WRITE (UNIT=obj%echounit, FMT='(a)', IOSTAT=eioerr) & & TRIM(val%chars()) - ! + IF (eioerr .NE. 0) THEN CALL e%raiseError(modName//'::'//myName//" - "// & &' - Error echoing line to UNIT='//tostring(obj%echounit)//& & ' (IOSTAT='//tostring(eioerr)//')!') END IF - ! + END IF - ! + val = TRIM(val) - ! + ELSEIF (ioerr .LT. IOSTAT_EOR) THEN - ! + ! Error reading line from input file - ! + CALL e%raiseError(modName//'::'//myName//" - "// & & ' - Error reading one line from input file (IOSTAT='// & & tostring(ioerr)//')!') - ! + ELSE - ! + ! Still reading current line. Append buffer to line - ! + val = val//buffer - ! + END IF END DO END IF diff --git a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 index 5a231c3de..68f03466d 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(UserFunction_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS @@ -25,14 +26,18 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE UserFunctionGetReturnType - SELECT CASE( TRIM(name) ) - CASE( "Scalar") - ans = Scalar - CASE( "Vector") - ans = Vector - CASE( "Matrix") - ans = Matrix - END SELECT +TYPE(String) :: name0 +name0 = UpperCase(name) +SELECT CASE (name0%chars()) +CASE ("SCALAR") + ans = Scalar +CASE ("VECTOR") + ans = Vector +CASE ("MATRIX") + ans = Matrix +END SELECT + +name0 = "" END PROCEDURE UserFunctionGetReturnType !---------------------------------------------------------------------------- @@ -40,16 +45,19 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE UserFunctionGetArgType - SELECT CASE( TRIM(name) ) - CASE( "Constant") - ans = Constant - CASE( "Space") - ans = Space - CASE( "SpaceTime") - ans = SpaceTime - CASE( "SolutionDependent") - ans = SolutionDependent - END SELECT +TYPE(String) :: name0 +name0 = UpperCase(name) +SELECT CASE (name0%chars()) +CASE ("CONSTANT") + ans = Constant +CASE ("SPACE") + ans = Space +CASE ("SPACETIME") + ans = SpaceTime +CASE ("OTHERS", "SOLUTIONDEPENDENT") + ans = SolutionDependent +END SELECT +name0 = "" END PROCEDURE UserFunctionGetArgType !---------------------------------------------------------------------------- @@ -57,12 +65,142 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetUserFunctionParam - INTEGER( I4B ) :: ierr - !> main - ierr = param%set( key="UserFunction/returnType", & - & value=returnType ) - ierr = param%set( key="UserFunction/argType", & - & value=argType ) +CHARACTER(*), PARAMETER :: myName = "SetUserFunctionParam()" +INTEGER(I4B) :: numArgs0, numReturns0, returnShape0(2) + +CALL Set(obj=param, dataType=1_I4B, prefix=myprefix, key="returnType", & + & VALUE=returnType) +CALL Set(obj=param, dataType=1_I4B, prefix=myprefix, key="argType", & + & VALUE=argType) + +IF (PRESENT(numArgs)) THEN + numArgs0 = numArgs +ELSE + SELECT CASE (argType) + CASE (Constant) + numArgs0 = DEFAULT_NUM_ARG_CONSTANT + CASE (Space) + numArgs0 = DEFAULT_NUM_ARG_SPACE + CASE (Time) + numArgs0 = DEFAULT_NUM_ARG_TIME + CASE (SpaceTime) + numArgs0 = DEFAULT_NUM_ARG_SPACETIME + CASE DEFAULT + numArgs0 = 0 + END SELECT +END IF + +IF (PRESENT(numReturns)) THEN + numReturns0 = numReturns +ELSE + SELECT CASE (returnType) + CASE (Scalar) + numReturns0 = DEFAULT_NUM_ARG_SCALAR + CASE (Vector) + numReturns0 = DEFAULT_NUM_ARG_VECTOR + CASE (Matrix) + numReturns0 = DEFAULT_NUM_ARG_MATRIX + CASE DEFAULT + numReturns0 = 0 + END SELECT +END IF + +returnShape0 = 0 +IF (returnType .EQ. Matrix) THEN + IF (.NOT. PRESENT(returnShape)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When returnType is Matrix, then'// & + & CHAR_LF//'returnShape should be present.') + RETURN + END IF + + IF (numReturns0 .NE. returnShape(1) * returnShape(2)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When returnType is Matrix, then '// & + & 'numReturns should be equal to the total number of elements.') + RETURN + END IF + + returnShape0 = returnShape +END IF + +CALL Set(obj=param, dataType=[1_I4B], prefix=myprefix, & + & key="returnShape", VALUE=returnShape0) + +IF (returnType .EQ. Scalar) THEN + IF (numReturns0 .NE. 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When returnType is Scalar, then '// & + & 'numReturns should be 1.') + RETURN + END IF +END IF + +IF (argType .EQ. Constant) THEN + IF (numArgs .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When argType is Constant, then '// & + & 'numArgs should be 0.') + RETURN + END IF +END IF + +IF (argType .EQ. Time) THEN + IF (numArgs .NE. 1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When argType is Time, then '// & + & 'numArgs should be 1.') + RETURN + END IF +END IF + +IF (argType .EQ. Space) THEN + IF (numArgs .NE. 3) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When argType is Space, then '// & + & 'numArgs should be 3.') + RETURN + END IF +END IF + +IF (argType .EQ. SpaceTime) THEN + IF (numArgs .NE. SpaceTime) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When argType is SpaceTime, then '// & + & 'numArgs should be 4.') + RETURN + END IF +END IF + +CALL Set(obj=param, dataType=1_I4B, prefix=myprefix, key="numArgs", & + & VALUE=numArgs0) + +CALL Set(obj=param, dataType=1_I4B, prefix=myprefix, key="numReturns", & + & VALUE=numReturns0) + +IF (PRESENT(luaScript)) THEN + IF (.NOT. PRESENT(luaFunctionName)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: When luaScript is given, you should'// & + & ' also mention the luaFunctionName.') + RETURN + END IF + + CALL Set(obj=param, dataType=.TRUE., prefix=myprefix, key="isLuaScript", & + & VALUE=.TRUE.) + CALL Set(obj=param, dataType="char", prefix=myprefix, key="luaScript", & + & VALUE=luaScript) + CALL Set(obj=param, dataType="char", prefix=myprefix, & + & key="luaFunctionName", VALUE=luaFunctionName) +ELSE + CALL Set(obj=param, dataType=.TRUE., prefix=myprefix, key="isLuaScript", & + & VALUE=.FALSE.) + CALL Set(obj=param, dataType="char", prefix=myprefix, key="luaScript", & + & VALUE="empty") + CALL Set(obj=param, dataType="char", prefix=myprefix, & + & key="luaFunctionName", VALUE="empty") +END IF + END PROCEDURE SetUserFunctionParam !---------------------------------------------------------------------------- @@ -70,19 +208,29 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_CheckEssentialParam - CHARACTER( LEN = * ), PARAMETER :: myName="auf_CheckEssentialParam" - INTEGER( I4B ) :: ii - INTEGER( I4B ), PARAMETER :: maxEssentialParam = 2 - TYPE( String ) :: essentialParam( maxEssentialParam ) - !> main - essentialParam(1) = "UserFunction/argType" - essentialParam(2) = "UserFunction/returnType" - DO ii = 1, maxEssentialParam - IF( .NOT. param%isPresent(key=TRIM(essentialParam(ii)%chars()))) THEN - CALL e%raiseError(modName//'::'//myName// " - "// & - & TRIM(essentialParam(ii)%chars()) // ' should be present in param') - END IF +CHARACTER(*), PARAMETER :: myName = "auf_CheckEssentialParam()" +INTEGER(I4B) :: ii +TYPE(String), ALLOCATABLE :: essentialParam(:) +TYPE(String) :: astr + +astr = "/isLuaScript/luaScript/numReturns/numArgs/returnType/argType"// & + &"/luaFunctionName/returnShape" + +CALL astr%Split(essentialParam, sep="/") +CALL CheckEssentialParam(obj=param, & + & keys=essentialParam, & + & prefix=myprefix, & + & myName=myName, & + & modName=modName) +!NOTE: CheckEssentialParam param is defined in easifemClasses FPL_Method + +IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" END DO + DEALLOCATE (essentialParam) +END IF +astr = "" END PROCEDURE auf_CheckEssentialParam !---------------------------------------------------------------------------- @@ -90,18 +238,23 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_Deallocate - !> main - obj%isInitiated = .TRUE. - obj%returnType = 0 - obj%argType = 0 - obj%isUserFunctionSet = .FALSE. - obj%scalarValue = 0.0_DFP - IF(ALLOCATED(obj%vectorValue)) DEALLOCATE(obj%vectorValue) - IF(ALLOCATED(obj%matrixValue)) DEALLOCATE(obj%matrixValue) - IF(ASSOCIATED(obj%userFunction)) THEN - CALL obj%userFunction%Deallocate() - END IF - obj%userFunction=>NULL() +!> main +obj%isInitiated = .FALSE. +obj%isUserFunctionSet = .FALSE. +obj%isLuaScript = .FALSE. +obj%luaScript = "" +obj%luaFunctionName = "" +obj%returnType = 0 +obj%returnShape = 0 +obj%argType = 0 +obj%numArgs = 0 +obj%numReturns = 0 +obj%scalarValue = 0.0_DFP +IF (ALLOCATED(obj%vectorValue)) DEALLOCATE (obj%vectorValue) +IF (ALLOCATED(obj%matrixValue)) DEALLOCATE (obj%matrixValue) +IF (ASSOCIATED(obj%scalarFunction)) obj%scalarFunction => NULL() +IF (ASSOCIATED(obj%vectorFunction)) obj%vectorFunction => NULL() +IF (ASSOCIATED(obj%matrixFunction)) obj%matrixFunction => NULL() END PROCEDURE auf_Deallocate !---------------------------------------------------------------------------- @@ -109,7 +262,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_Final - CALL obj%Deallocate() +CALL obj%DEALLOCATE() END PROCEDURE auf_Final !---------------------------------------------------------------------------- @@ -117,13 +270,37 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_Initiate - obj%returnType = returnType - obj%argType = argType - obj%isInitiated = .TRUE. +CALL obj%DEALLOCATE() +CALL obj%CheckEssentialParam(param) + +CALL GetValue(obj=param, prefix=myprefix, key="returnType", & + & VALUE=obj%returnType) + +CALL GetValue(obj=param, prefix=myprefix, key="argType", & + & VALUE=obj%argType) + +CALL GetValue(obj=param, prefix=myprefix, key="isLuaScript", & + & VALUE=obj%isLuaScript) + +CALL GetValue(obj=param, prefix=myprefix, key="luaScript", & + & VALUE=obj%luaScript) + +CALL GetValue(obj=param, prefix=myprefix, key="luaFunctionName", & + & VALUE=obj%luaFunctionName) + +CALL GetValue(obj=param, prefix=myprefix, key="numArgs", & + & VALUE=obj%numArgs) + +CALL GetValue(obj=param, prefix=myprefix, key="numReturns", & + & VALUE=obj%numReturns) + +CALL GetValue(obj=param, prefix=myprefix, key="returnShape", & + & VALUE=obj%returnShape) +obj%isInitiated = .TRUE. END PROCEDURE auf_Initiate !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -END SUBMODULE ConstructorMethods \ No newline at end of file +END SUBMODULE ConstructorMethods diff --git a/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 index 7580c8793..4ee12dfa8 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 @@ -21,59 +21,385 @@ CONTAINS !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE auf_getScalarValue - IF( obj%isUserFunctionSet .AND. ASSOCIATED( obj%userFunction ) ) THEN - CALL obj%userFunction%Get( args=args, val=val ) +MODULE PROCEDURE auf_GetScalarValue +LOGICAL(LGT) :: isOK, isNotOK +CHARACTER(*), PARAMETER :: myName = "auf_GetScalarValue()" +#ifdef USE_LUA +TYPE(C_PTR) :: l +INTEGER(I4B) :: rc, nargs, nresults, iarg +LOGICAL(LGT) :: isFunction +#endif + +isOK = obj%returnType .EQ. Scalar +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The user function is not configured for '// & + & ' returnType = Scalar') + RETURN +END IF + +val = obj%scalarValue + +IF (obj%isUserFunctionSet) THEN + isOK = ASSOCIATED(obj%scalarFunction) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isUserFunctionSet is true '// & + & CHAR_LF//' but obj%scalarFunction is not ASSOCIATED.') + RETURN + END IF + val = obj%scalarFunction(x=args) +END IF + +#ifdef USE_LUA + +IF (obj%isLuaScript) THEN + nargs = obj%numArgs + nresults = obj%numReturns + + isNotOK = nresults .NE. 1_I4B + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%numReturns should be 1'// & + & CHAR_LF//' but it is '//tostring(obj%numReturns)) + RETURN + END IF + + IF (PRESENT(args)) THEN + isNotOK = nargs .NE. SIZE(args) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::numArgs( '//CHAR_LF// & + & tostring(obj%numArgs)//' ) should be same as size of args ('// & + & CHAR_LF//tostring(SIZE(args))//').') + RETURN + END IF + ELSE - val = obj%scalarValue + + isNotOK = nargs .NE. 0_I4B + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::numArgs( '//CHAR_LF// & + & tostring(obj%numArgs)//' ) should be equal to 0 when '// & + & CHAR_LF//'args is not present.') + RETURN + END IF + END IF + + l = lual_newstate() + CALL lual_openlibs(l) + rc = lual_dofile(l, obj%luaScript%chars()) + rc = lua_getglobal(l, obj%luaFunctionName%chars()) + isFunction = lua_isfunction(l, -1) .EQ. 1 + + IF (.NOT. isFunction) THEN + CALL lua_close(l) + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isLuaScript is TRUE'// & + & CHAR_LF//'In the lua script'//obj%luaScript%chars()// & + & CHAR_LF//'lua function named '//obj%luaFunctionName%chars()// & + & CHAR_LF//' is not a function.') + RETURN + END IF + + DO iarg = 1, nargs + CALL lua_pushnumber(l, REAL(args(iarg), kind=lua_number)) + END DO + + rc = lua_pcall(l, nargs, nresults, 0) + IF (rc .NE. lua_ok) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isLuaScript is TRUE'// & + & CHAR_LF//'Some error occured while calling lua_pcall(); '// & + & CHAR_LF//tostring(rc)) + RETURN END IF -END PROCEDURE auf_getScalarValue + val = REAL(lua_tonumber(l, -1), kind=DFP) + CALL lua_pop(l, 1) + CALL lua_close(l) +END IF + +#else +IF (obj%isLuaScript) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: Currently lua script cannot be used for '// & + & ' UserFunction. ') + RETURN +END IF +#endif + +END PROCEDURE auf_GetScalarValue !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE auf_getVectorValue - IF( obj%isUserFunctionSet .AND. ASSOCIATED( obj%userFunction ) ) THEN - CALL obj%userFunction%Get( args=args, val=val ) +MODULE PROCEDURE auf_GetVectorValue +LOGICAL(LGT) :: isOK, isNotOK +CHARACTER(*), PARAMETER :: myName = "auf_GetVectorValue()" + +#ifdef USE_LUA +TYPE(C_PTR) :: l +INTEGER(I4B) :: rc, nargs, nresults, iarg +LOGICAL(LGT) :: isFunction +#endif + +isOK = obj%returnType .EQ. Vector +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The user function is not configured for '// & + & ' returnType = Vector') + RETURN +END IF + +IF (ALLOCATED(obj%vectorValue)) THEN + CALL Reallocate(val, obj%numReturns) +#ifdef USE_BLAS95 + CALL Copy(x=val, y=obj%vectorValue) +#else + val = obj%vectorValue +#endif +END IF + +IF (obj%isUserFunctionSet) THEN + isOK = ASSOCIATED(obj%vectorFunction) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isUserFunctionSet is true '// & + & CHAR_LF//' but obj%vectorFunction is not ASSOCIATED.') + RETURN + END IF + CALL Reallocate(val, obj%numReturns) + val = obj%vectorFunction(x=args) +END IF + +#ifdef USE_LUA + +IF (obj%isLuaScript) THEN + nargs = obj%numArgs + nresults = obj%numReturns + + CALL Reallocate(val, obj%numReturns) + + IF (PRESENT(args)) THEN + isNotOK = nargs .NE. SIZE(args) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::numArgs( '// & + & CHAR_LF//tostring(obj%numArgs)// & + & ' ) should be same as size of args ('// & + & CHAR_LF//tostring(SIZE(args))//').') + RETURN + END IF + ELSE - val = obj%vectorValue + + isNotOK = nargs .NE. 0_I4B + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::numArgs( '//CHAR_LF// & + & tostring(obj%numArgs)//' ) should be equal to 0 when '// & + & CHAR_LF//'args is not present.') + RETURN + END IF END IF -END PROCEDURE auf_getVectorValue + + l = lual_newstate() + CALL lual_openlibs(l) + rc = lual_dofile(l, obj%luaScript%chars()) + rc = lua_getglobal(l, obj%luaFunctionName%chars()) + isFunction = lua_isfunction(l, -1) .EQ. 1 + + IF (.NOT. isFunction) THEN + CALL lua_close(l) + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isLuaScript is TRUE'// & + & CHAR_LF//'In the lua script'//obj%luaScript%chars()// & + & CHAR_LF//'lua function named '//obj%luaFunctionName%chars()// & + & CHAR_LF//' is not a function.') + RETURN + END IF + + DO iarg = 1, nargs + CALL lua_pushnumber(l, REAL(args(iarg), kind=lua_number)) + END DO + + rc = lua_pcall(l, nargs, nresults, 0) + IF (rc .NE. lua_ok) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isLuaScript is TRUE'// & + & CHAR_LF//'Some error occured while calling lua_pcall(); '// & + & CHAR_LF//tostring(rc)) + RETURN + END IF + + DO iarg = nresults, 1, -1 + val(iarg) = REAL(lua_tonumber(l, nresults + iarg - 1), kind=DFP) + END DO + CALL lua_pop(l, nresults) + CALL lua_close(l) +END IF + +#else +IF (obj%isLuaScript) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: Currently lua script cannot be used for '// & + & ' UserFunction. ') + RETURN +END IF +#endif + +END PROCEDURE auf_GetVectorValue !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE auf_getMatrixValue - IF( obj%isUserFunctionSet .AND. ASSOCIATED( obj%userFunction ) ) THEN - CALL obj%userFunction%Get( args=args, val=val ) +MODULE PROCEDURE auf_GetMatrixValue +LOGICAL(LGT) :: isOK, isNotOK +CHARACTER(*), PARAMETER :: myName = "auf_GetMatrixValue()" +INTEGER(I4B) :: myshape(2) +#ifdef USE_LUA +TYPE(C_PTR) :: l +INTEGER(I4B) :: rc, nargs, nresults, iarg +LOGICAL(LGT) :: isFunction +REAL(DFP), ALLOCATABLE :: dummyvec(:) +#endif + +isOK = obj%returnType .EQ. Matrix +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: The user function is not configured for '// & + & ' returnType = Vector') + RETURN +END IF + +IF (ALLOCATED(obj%matrixValue)) THEN + myshape = SHAPE(obj%matrixValue) + CALL Reallocate(val, myshape(1), myshape(2)) + val = obj%matrixValue +END IF + +IF (obj%isUserFunctionSet) THEN + isOK = ASSOCIATED(obj%matrixFunction) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isUserFunctionSet '// & + & CHAR_LF//'is true but obj%matrixFunction is not ASSOCIATED.') + RETURN + END IF + CALL Reallocate(val, obj%returnShape(1), obj%returnShape(2)) + val = obj%matrixFunction(x=args) +END IF + +#ifdef USE_LUA + +IF (obj%isLuaScript) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP Progress]') + nargs = obj%numArgs + nresults = obj%numReturns + + CALL Reallocate(dummyvec, nresults) + + IF (PRESENT(args)) THEN + isNotOK = nargs .NE. SIZE(args) + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::numArgs( '// & + & CHAR_LF//tostring(obj%numArgs)// & + & ' ) should be same as size of args ('// & + & CHAR_LF//tostring(SIZE(args))//').') + RETURN + END IF + ELSE - val = obj%matrixValue + + isNotOK = nargs .NE. 0_I4B + IF (isNotOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::numArgs( '//CHAR_LF// & + & tostring(obj%numArgs)//' ) should be equal to 0 when '// & + & CHAR_LF//'args is not present.') + RETURN + END IF END IF -END PROCEDURE auf_getMatrixValue + + l = lual_newstate() + CALL lual_openlibs(l) + rc = lual_dofile(l, obj%luaScript%chars()) + rc = lua_getglobal(l, obj%luaFunctionName%chars()) + isFunction = lua_isfunction(l, -1) .EQ. 1 + + IF (.NOT. isFunction) THEN + CALL lua_close(l) + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isLuaScript is TRUE'// & + & CHAR_LF//'In the lua script'//obj%luaScript%chars()// & + & CHAR_LF//'lua function named '//obj%luaFunctionName%chars()// & + & CHAR_LF//' is not a function.') + RETURN + END IF + + DO iarg = 1, nargs + CALL lua_pushnumber(l, REAL(args(iarg), kind=lua_number)) + END DO + + rc = lua_pcall(l, nargs, nresults, 0) + IF (rc .NE. lua_ok) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: UserFunction_::obj%isLuaScript is TRUE'// & + & CHAR_LF//'Some error occured while calling lua_pcall(); '// & + & CHAR_LF//tostring(rc)) + RETURN + END IF + + DO iarg = nresults, 1, -1 + dummyvec(iarg) = REAL(lua_tonumber(l, nresults + iarg - 1), kind=DFP) + END DO + CALL lua_pop(l, nresults) + CALL lua_close(l) + + CALL Reallocate(val, obj%returnShape(1), obj%returnShape(2)) + val = RESHAPE(dummyvec, obj%returnShape) + IF (ALLOCATED(dummyvec)) THEN + DEALLOCATE (dummyvec) + END IF +END IF + +#else +IF (obj%isLuaScript) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: Currently lua script cannot be used for '// & + & ' UserFunction. ') + RETURN +END IF +#endif + +END PROCEDURE auf_GetMatrixValue !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE auf_getArgType - ans = obj%argType -END PROCEDURE auf_getArgType +MODULE PROCEDURE auf_GetArgType +ans = obj%argType +END PROCEDURE auf_GetArgType !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE auf_getReturnType - ans = obj%returnType -END PROCEDURE auf_getReturnType +MODULE PROCEDURE auf_GetReturnType +ans = obj%returnType +END PROCEDURE auf_GetReturnType !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -END SUBMODULE GetMethods \ No newline at end of file +END SUBMODULE GetMethods diff --git a/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 index 5d38055c7..7862b3ca3 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 @@ -13,10 +13,16 @@ ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see -! SUBMODULE(UserFunction_Class) IOMethods USE BaseMethod +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat IMPLICIT NONE CONTAINS @@ -25,36 +31,61 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_Display - CALL Display( msg, unitNo=unitNo ) - IF( obj%isUserFunctionSet ) THEN - CALL Display( "# isUserFunctionSet: TRUE", unitNo=unitNo ) - CALL obj%userFunction%Display("display from useFunction: ", & - & unitNo=unitNo) - ELSE - CALL Display( "# isUserFunctionSet: FALSE", unitNo=unitNo ) - CALL Display(NAME_RETURN_TYPE(obj%returnType), "# returnType: ", & - & unitNo=unitNo ) - CALL Display(NAME_ARG_TYPE(obj%argType), "# argType: ", & - & unitNo=unitNo ) - IF( obj%argType .EQ. CONSTANT ) THEN - SELECT CASE( obj%returnType ) - CASE( Scalar ) - CALL Display( obj%scalarValue, "# scalarValue: ", unitNo=unitNo ) - CASE( Vector ) - IF( ALLOCATED(obj%vectorValue )) THEN - CALL Display( obj%vectorValue, "# vectorValue: ", unitNo=unitNo ) - ELSE - CALL Display( "# vectorValue: NOT ALLOCATED", unitNo=unitNo) - END IF - CASE( Matrix ) - IF( ALLOCATED(obj%matrixValue )) THEN - CALL Display( obj%matrixValue, "# matrixValue: ", unitNo=unitNo ) - ELSE - CALL Display( "# matrixValue: NOT ALLOCATED", unitNo=unitNo) - END IF - END SELECT +LOGICAL(LGT) :: bool1 +CALL Display(msg, unitNo=unitNo) +CALL Display(obj%isInitiated, "isInitiated: ", unitNo=unitNo) + +IF (.NOT. obj%isInitiated) THEN + RETURN +END IF + +CALL Display(obj%isUserFunctionSet, "isUserFunctionSet: ", unitNo=unitNo) +CALL Display(obj%isLuaScript, "isLuaScript: ", unitNo=unitNo) +IF (obj%isLuaScript) THEN + CALL display(obj%luaScript, "luaScript: ", unitNo=unitNo) + CALL display(obj%luaFunctionName, "luaFunctionName: ", unitNo=unitNo) +END IF + +CALL Display(NAME_RETURN_TYPE(obj%returnType), "returnType: ", & + & unitNo=unitNo) +IF (obj%returnType .EQ. Matrix) THEN + CALL Display(obj%returnShape, "Shape of returnType: ", unitNo=unitNo) +END IF + +CALL Display(NAME_ARG_TYPE(obj%argType), "argType: ", & + & unitNo=unitNo) + +CALL Display(obj%numArgs, "number of arguments: ", unitNo=unitNo) +CALL Display(obj%numReturns, "number of returns: ", unitNo=unitNo) + +bool1 = ASSOCIATED(obj%scalarFunction) +CALL Display(bool1, msg="scalarFunction ASSOCIATED: ", unitno=unitno) + +bool1 = ASSOCIATED(obj%vectorFunction) +CALL Display(bool1, msg="vectorFunction ASSOCIATED: ", unitno=unitno) + +bool1 = ASSOCIATED(obj%matrixFunction) +CALL Display(bool1, msg="matrixFunction ASSOCIATED: ", unitno=unitno) + +IF (obj%argType .EQ. CONSTANT) THEN + SELECT CASE (obj%returnType) + CASE (Scalar) + CALL Display(obj%scalarValue, "scalarValue: ", unitNo=unitNo) + CASE (Vector) + IF (ALLOCATED(obj%vectorValue)) THEN + CALL Display(obj%vectorValue, "vectorValue: ", unitNo=unitNo) + ELSE + CALL Display("vectorValue: NOT ALLOCATED", unitNo=unitNo) END IF - END IF + CASE (Matrix) + IF (ALLOCATED(obj%matrixValue)) THEN + CALL Display(obj%matrixValue, "matrixValue: ", unitNo=unitNo) + ELSE + CALL Display("matrixValue: NOT ALLOCATED", unitNo=unitNo) + END IF + END SELECT +END IF + END PROCEDURE auf_Display !---------------------------------------------------------------------------- @@ -62,81 +93,83 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_Import - CHARACTER( LEN = * ), PARAMETER :: myName= "auf_Import" - TYPE( String ) :: dsetname, strval - !> main - !> info - CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Importing the instance of UserFunction_ data") - !> check - IF( .NOT. hdf5%isOpen() ) THEN +CHARACTER(*), PARAMETER :: myName = "auf_Import" +TYPE(String) :: dsetname, strval +!> main +!> info +CALL e%raiseInformation(modName//"::"//myName//" - "// & + & "Importing the instance of UserFunction_ data") +!> check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file is not opened') +END IF +!> check +IF (.NOT. hdf5%isRead()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file does not have read permission') +END IF +!> isUserFunctionSet +dsetname = TRIM(group)//"/isUserFunctionSet" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) +ELSE + obj%isUserFunctionSet = .FALSE. +END IF +!> isUserFunctionSet +IF (obj%isUserFunctionSet) THEN + ! dsetname = TRIM(group)//"/userFunction" + ! ALLOCATE (obj%userFunction) + ! CALL obj%userFunction%IMPORT(hdf5=hdf5, group=dsetname%chars()) + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: currently import does not work for useFunction') +ELSE + !> returnType + dsetname = TRIM(group)//"/returnType" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') + & 'dsetname '//dsetname%chars()//'is not present in HDFFile_') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + obj%returnType = UserFunctionGetReturnType(strval%chars()) END IF - !> check - IF( .NOT. hdf5%isRead() ) THEN + !> argType + dsetname = TRIM(group)//"/argType" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have read permission') - END IF - !> isUserFunctionSet - dsetname=trim(group)//"/isUserFunctionSet" - IF( hdf5%pathExists(dsetname%chars()) ) THEN - CALL hdf5%read(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) + & 'dsetname '//dsetname%chars()//'is not present in HDFFile_') ELSE - obj%isUserFunctionSet = .FALSE. + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + obj%argType = UserFunctionGetArgType(strval%chars()) END IF - !> isUserFunctionSet - IF( obj%isUserFunctionSet ) THEN - dsetname=trim(group)//"/userFunction" - ALLOCATE(obj%userFunction) - CALL obj%userFunction%Import(hdf5=hdf5, group=dsetname%chars()) + !> check the argType, and decide the importer + IF (obj%argType .EQ. CONSTANT) THEN + !> scalarValue, vectorValue, matrixValue + SELECT CASE (obj%returnType) + CASE (SCALAR) + !> scalarValue + dsetname = TRIM(group)//"/scalarValue" + IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%scalarValue) + END IF + CASE (VECTOR) + !> vectorValue + dsetname = TRIM(group)//"/vectorValue" + IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%vectorValue) + END IF + CASE (MATRIX) + !> matrixValue + dsetname = TRIM(group)//"/matrixValue" + IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%matrixValue) + END IF + END SELECT ELSE - !> returnType - dsetname=TRIM(group)//"/returnType" - IF( .NOT. hdf5%pathExists(dsetname%chars()) ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'dsetname '// dsetname%chars() // 'is not present in HDFFile_') - ELSE - CALL hdf5%read(dsetname=dsetname%chars(), vals=strval) - obj%returnType=UserFunctionGetReturnType( strval%chars() ) - END IF - !> argType - dsetname=TRIM(group)//"/argType" - IF( .NOT. hdf5%pathExists(dsetname%chars()) ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'dsetname '// dsetname%chars() // 'is not present in HDFFile_') - ELSE - CALL hdf5%read(dsetname=dsetname%chars(), vals=strval) - obj%argType=UserFunctionGetArgType( strval%chars() ) - END IF - !> check the argType, and decide the importer - IF( obj%argType .EQ. CONSTANT ) THEN - !> scalarValue, vectorValue, matrixValue - SELECT CASE( obj%returnType ) - CASE( SCALAR ) - !> scalarValue - dsetname=trim(group)//"/scalarValue" - IF( hdf5%pathExists(dsetname%chars()) ) THEN - CALL hdf5%read(dsetname=dsetname%chars(), vals=obj%scalarValue) - ENDIF - CASE( VECTOR ) - !> vectorValue - dsetname=trim(group)//"/vectorValue" - IF( hdf5%pathExists(dsetname%chars()) ) THEN - CALL hdf5%read(dsetname=dsetname%chars(), vals=obj%vectorValue) - ENDIF - CASE( MATRIX ) - !> matrixValue - dsetname=trim(group)//"/matrixValue" - IF( hdf5%pathExists(dsetname%chars()) ) THEN - CALL hdf5%read(dsetname=dsetname%chars(), vals=obj%matrixValue) - ENDIF - END SELECT - ELSE - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Currently, EASIFEM Supports import of constant userFunction.') - END IF + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Currently, EASIFEM Supports import of constant userFunction.') END IF +END IF END PROCEDURE auf_Import !---------------------------------------------------------------------------- @@ -144,67 +177,307 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE auf_Export - CHARACTER( LEN = * ), PARAMETER :: myName= "auf_Export" - TYPE( String ) :: dsetname, strval - !> main - !> info - CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Exporting the instance of UserFunction_ data") - !> check - IF( .NOT. hdf5%isOpen() ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') - END IF - !> check - IF( .NOT. hdf5%isWrite() ) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have write permission') - END IF +CHARACTER(*), PARAMETER :: myName = "auf_Export" +TYPE(String) :: dsetname, strval + +!> info +CALL e%raiseInformation(modName//"::"//myName//" - "// & + & "Exporting the instance of UserFunction_ data") + +!> check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file is not opened') +END IF + +!> check +IF (.NOT. hdf5%isWrite()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file does not have write permission') +END IF + +!> isUserFunctionSet +IF (obj%isUserFunctionSet) THEN + !> isUserFunctionSet + ! dsetname = TRIM(group)//"/isUserFunctionSet" + ! CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) + ! !> returnType + ! dsetname = TRIM(group)//"/userFunction" + ! CALL obj%userFunction%Export(hdf5=hdf5, group=dsetname%chars()) + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: Currently export function does not work '// & + & ' for UserFunction.') +ELSE !> isUserFunctionSet - IF( obj%isUserFunctionSet ) THEN - !> isUserFunctionSet - dsetname=trim(group)//"/isUserFunctionSet" - CALL hdf5%write(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) - !> returnType - dsetname=trim(group)//"/userFunction" - CALL obj%userFunction%Export(hdf5=hdf5, group=dsetname%chars()) + dsetname = TRIM(group)//"/isUserFunctionSet" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) + !> returnType + dsetname = TRIM(group)//"/returnType" + strval = NAME_RETURN_TYPE(obj%returnType) + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) + !> argType + dsetname = TRIM(group)//"/argType" + strval = NAME_ARG_TYPE(obj%argType) + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) + !> + IF (obj%argType .EQ. CONSTANT) THEN + SELECT CASE (obj%returnType) + CASE (SCALAR) + !> scalarValue + dsetname = TRIM(group)//"/scalarValue" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%scalarValue) + CASE (VECTOR) + !> vectorValue + dsetname = TRIM(group)//"/vectorValue" + IF (ALLOCATED(obj%vectorValue)) & + & CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%vectorValue) + CASE (MATRIX) + !> matrixValue + dsetname = TRIM(group)//"/matrixValue" + IF (ALLOCATED(obj%matrixValue)) & + & CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%matrixValue) + END SELECT ELSE - !> isUserFunctionSet - dsetname=trim(group)//"/isUserFunctionSet" - CALL hdf5%write(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) - !> returnType - dsetname=trim(group)//"/returnType" - strval = NAME_RETURN_TYPE(obj%returnType) - CALL hdf5%write(dsetname=dsetname%chars(), vals=strval) - !> argType - dsetname=trim(group)//"/argType" - strval = NAME_ARG_TYPE(obj%argType) - CALL hdf5%write(dsetname=dsetname%chars(), vals=strval) - !> - IF( obj%argType .EQ. CONSTANT ) THEN - SELECT CASE( obj%returnType ) - CASE( SCALAR ) - !> scalarValue - dsetname=trim(group)//"/scalarValue" - CALL hdf5%write(dsetname=dsetname%chars(), vals=obj%scalarValue) - CASE( VECTOR ) - !> vectorValue - dsetname=trim(group)//"/vectorValue" - IF( ALLOCATED(obj%vectorValue)) & - & CALL hdf5%write(dsetname=dsetname%chars(), vals=obj%vectorValue) - CASE( MATRIX ) - !> matrixValue - dsetname=trim(group)//"/matrixValue" - IF( ALLOCATED(obj%matrixValue)) & - & CALL hdf5%write(dsetname=dsetname%chars(), vals=obj%matrixValue) - END SELECT - ELSE - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Currently, EASIFEM Supports import of constant userFunction.') - END IF + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Currently, EASIFEM Supports import of constant userFunction.') END IF +END IF END PROCEDURE auf_Export +!---------------------------------------------------------------------------- +! ImportParamFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE auf_ImportParamFromToml +CHARACTER(*), PARAMETER :: myName = "auf_ImportParamFromToml()" +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: bool1, isLuaScript, isFound +INTEGER(I4B) :: argType, returnType, numReturns, numArgs +TYPE(String) :: astr, luaScript, luaFunctionName +INTEGER(I4B), ALLOCATABLE :: returnShape(:) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportParamFromToml()') +#endif + +CALL toml_get(table, "returnType", astr%raw, origin=origin, stat=stat) +bool1 = stat .NE. toml_stat%success +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: returnType should be present, and '// & + & 'it is a string.') + RETURN +END IF +returnType = UserFunctionGetReturnType(astr%chars()) + +CALL Reallocate(returnShape, 2) +returnShape = [0, 0] +IF (returnType .EQ. Matrix) THEN + CALL GetValue(table=table, key="returnShape", VALUE=returnShape, & + & origin=origin, stat=stat, isFound=isFound) + bool1 = (stat .NE. toml_stat%success) .OR. (.NOT. isFound) + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: when returnType is Matrix, then '// & + & 'returnShape should be present. It is a vector of integers'// & + & ' and size 2.') + RETURN + END IF +END IF + +CALL toml_get(table, "argType", astr%raw, origin=origin, stat=stat) +bool1 = stat .NE. toml_stat%success +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: argType should be present, and '// & + & 'it is a string.') + RETURN +END IF +argType = UserFunctionGetArgType(astr%chars()) + +CALL toml_get(table, "numArgs", numArgs, origin=origin, stat=stat) +bool1 = stat .NE. toml_stat%success +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: numArgs should be present, and '// & + & 'it is a scalar integer number.') + RETURN +END IF + +CALL toml_get(table, "numReturns", numReturns, origin=origin, stat=stat) +bool1 = stat .NE. toml_stat%success +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: numReturns should be present, and '// & + & 'it is a scalar integer number.') + RETURN +END IF + +CALL toml_get(table, "luaScript", luaScript%raw, origin=origin, stat=stat) +isLuaScript = stat .EQ. toml_stat%success + +IF (isLuaScript) THEN + CALL toml_get(table, "luaFunctionName", luaFunctionName%raw, & + & origin=origin, stat=stat) + bool1 = stat .NE. toml_stat%success + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: when you specify luaScript you should also '// & + & 'specify luaFunctionName.') + RETURN + END IF +END IF + +IF (isLuaScript) THEN + CALL SetUserFunctionParam(param=param, & + & returnType=returnType, & + & returnShape=returnShape, & + & argType=argType, & + & numArgs=numArgs, & + & numReturns=numReturns, & + & luaScript=luaScript%chars(), & + & luaFunctionName=luaFunctionName%chars()) +ELSE + CALL SetUserFunctionParam(param=param, & + & returnType=returnType, & + & returnShape=returnShape, & + & argType=argType, & + & numArgs=numArgs, & + & numReturns=numReturns) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE auf_ImportParamFromToml + +!---------------------------------------------------------------------------- +! ImportParamFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE auf_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "auf_ImportFromToml1()" +TYPE(ParameterList_) :: param +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: bool1, isFound +REAL(DFP) :: scalarValue +REAL(DFP), ALLOCATABLE :: vectorValue(:), matrixValue(:, :) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +CALL param%Initiate() +CALL obj%ImportParamFromToml(param=param, table=table) +CALL obj%Initiate(param=param) + +IF (.NOT. obj%isLuaScript) THEN + SELECT CASE (obj%returnType) + CASE (Scalar) + CALL toml_get(table, "scalarValue", scalarValue, & + & origin=origin, stat=stat) + IF (stat .NE. toml_stat%success) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: returnType is Scalar, and '// & + & CHAR_LF//'argType is Constant. '// & + & CHAR_LF//'Therefore, scalarValue should be present.') + RETURN + END IF + CALL obj%Set(scalarValue=scalarValue) + CASE (Vector) + CALL GetValue(table=table, key="vectorValue", & + & VALUE=vectorValue, origin=origin, stat=stat, isFound=isFound) + + bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: returnType is Vector, and '// & + & CHAR_LF//'argType is Constant. '// & + & CHAR_LF//'Therefore, vectorValue should be present.') + RETURN + END IF + + CALL obj%Set(vectorValue=vectorValue) + IF (ALLOCATED(vectorValue)) DEALLOCATE (vectorValue) + + CASE (Matrix) + CALL GetValue(table=table, key="matrixValue", & + & VALUE=matrixValue, origin=origin, stat=stat, isFound=isFound) + + bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: returnType is Matrix, and '// & + & CHAR_LF//'argType is Constant. '// & + & CHAR_LF//'Therefore, matrixValue should be present.') + RETURN + END IF + + CALL obj%Set(matrixValue=matrixValue) + IF (ALLOCATED(matrixValue)) DEALLOCATE (matrixValue) + END SELECT +END IF + +CALL param%DEALLOCATE() +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml()') +#endif +END PROCEDURE auf_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportParamFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE auf_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "auf_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +INTEGER(I4B) :: origin, stat + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +node => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find ['//tomlName//"] table in config.") +END IF + +CALL obj%ImportFromToml(table=node) + +#ifdef DEBUG_VER +IF (PRESENT(printToml)) THEN + CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & + & unitNo=stdout) +END IF +#endif + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE auf_ImportFromToml2 + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 index dbcd83ee7..3d3ddd18d 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 @@ -20,28 +20,8 @@ IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! SET -!---------------------------------------------------------------------------- - -MODULE PROCEDURE auf_Set1 - !> main - obj%isUserFunctionSet = .TRUE. - obj%userFunction => anotherobj -END PROCEDURE auf_Set1 - -!---------------------------------------------------------------------------- -! SET -!---------------------------------------------------------------------------- - -MODULE PROCEDURE auf_Set2 - IF( PRESENT( scalarValue ) ) obj%scalarValue=scalarValue - IF( PRESENT( vectorValue ) ) obj%vectorValue=vectorValue - IF( PRESENT( matrixValue ) ) obj%matrixValue=matrixValue -END PROCEDURE auf_Set2 - !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -END SUBMODULE SetMethods \ No newline at end of file +END SUBMODULE SetMethods diff --git a/src/submodules/Vector/src/Vector_Class@SetMethods.F90 b/src/submodules/Vector/src/Vector_Class@SetMethods.F90 index 8e4e6d848..2a30608dd 100644 --- a/src/submodules/Vector/src/Vector_Class@SetMethods.F90 +++ b/src/submodules/Vector/src/Vector_Class@SetMethods.F90 @@ -25,27 +25,26 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set1 - CHARACTER( LEN = * ), PARAMETER :: myName="vec_set1" - !! #ifdef DEBUG_VER - !! - IF( .NOT. obj%isInitiated ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - IF( obj%tSize .GE. nodenum ) THEN +CHARACTER(*), PARAMETER :: myName = "vec_set1" + +IF (.NOT. obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +END IF + +IF (obj%tSize .GE. nodenum) THEN + CALL set(obj%realVec, nodenum=[nodenum], VALUE=[VALUE]) +ELSE + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'nodenum :: '//tostring(nodenum)// & + & " is greater than tSize : "//tostring(obj%tSize)) +END IF + +#else +CALL set(obj%realVec, nodenum=[nodenum], VALUE=[VALUE]) #endif - !! - CALL set( obj%realVec, nodenum=[nodenum], value=[value] ) - !! -#ifdef DEBUG_VER - ELSE - CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'nodenum :: '// trim(str(nodenum, .true.)) // " is greater than tSize : "//& - & trim( str( obj%tSize, .true. )) ) - END IF -#endif - !! + END PROCEDURE vec_set1 !---------------------------------------------------------------------------- @@ -53,19 +52,14 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set2 - CHARACTER( LEN = * ), PARAMETER :: myName = "vec_set2" - !! #ifdef DEBUG_VER - IF( .NOT. obj%isInitiated ) THEN - !! - CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - END IF +CHARACTER(*), PARAMETER :: myName = "vec_set2" +IF (.NOT. obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +END IF #endif - !! - CALL set( obj%realVec, value=value ) - !! +CALL set(obj%realVec, VALUE=VALUE) END PROCEDURE vec_set2 !---------------------------------------------------------------------------- @@ -73,20 +67,16 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set3 - CHARACTER( LEN = * ), PARAMETER :: myName="vec_set3" - !! #ifdef DEBUG_VER - IF( .NOT. obj%isInitiated ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - IF( obj%tSize .NE. SIZE(value) ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Size of given value is not same as the size of real vector' ) +CHARACTER(*), PARAMETER :: myName = "vec_set3" +IF (.NOT. obj%isInitiated) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +IF (obj%tSize .NE. SIZE(VALUE)) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Size of given value is not same as the size of real vector') #endif - !! - CALL set( obj%realVec, value=value ) - !! +CALL set(obj%realVec, VALUE=VALUE) END PROCEDURE vec_set3 !---------------------------------------------------------------------------- @@ -94,21 +84,16 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set4 - CHARACTER( LEN = * ), PARAMETER :: myName="vec_set4" - !! #ifdef DEBUG_VER - IF( .NOT. obj%isInitiated ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - IF( ANY( nodenum .GT. obj%tSize ) ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Some of the nodenum are out of bound, nodenum>tSize' ) - !! +CHARACTER(*), PARAMETER :: myName = "vec_set4" +IF (.NOT. obj%isInitiated) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +IF (ANY(nodenum .GT. obj%tSize)) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Some of the nodenum are out of bound, nodenum>tSize') #endif - !! - CALL set( obj%realVec, nodenum=nodenum, value=value ) - !! +CALL set(obj%realVec, nodenum=nodenum, VALUE=VALUE) END PROCEDURE vec_set4 !---------------------------------------------------------------------------- @@ -116,21 +101,17 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set5 - CHARACTER( LEN = * ), PARAMETER :: myName="vec_set5" - !! #ifdef DEBUG_VER - IF( .NOT. obj%isInitiated ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - IF( istart .GT. obj%tsize .OR. iend .GT. obj%tsize ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Index is out of bound' ) +CHARACTER(*), PARAMETER :: myName = "vec_set5" +IF (.NOT. obj%isInitiated) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +IF (istart .GT. obj%tsize .OR. iend .GT. obj%tsize) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Index is out of bound') #endif - !! - CALL set( obj%realVec, istart=istart, iend=iend, stride=stride, & - & value=value ) - !! +CALL set(obj%realVec, istart=istart, iend=iend, stride=stride, & + & VALUE=VALUE) END PROCEDURE vec_set5 !---------------------------------------------------------------------------- @@ -138,22 +119,18 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set6 - CHARACTER( LEN = * ), PARAMETER :: myName="vec_set6" - !! #ifdef DEBUG_VER - IF( .NOT. obj%isInitiated ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - IF( istart .GT. obj%tsize .OR. iend .GT. obj%tsize & - & .OR. INT( ( iend - istart + stride )/ stride ) .GT. obj%tsize ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Index is out of bound' ) +CHARACTER(*), PARAMETER :: myName = "vec_set6" +IF (.NOT. obj%isInitiated) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +IF (istart .GT. obj%tsize .OR. iend .GT. obj%tsize & + & .OR. INT((iend - istart + stride) / stride) .GT. obj%tsize) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Index is out of bound') #endif - !! - CALL set( obj%realVec, istart=istart, iend=iend, stride=stride, & - & value=value ) - !! +CALL set(obj%realVec, istart=istart, iend=iend, stride=stride, & + & VALUE=VALUE) END PROCEDURE vec_set6 !---------------------------------------------------------------------------- @@ -161,88 +138,75 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vec_set7 - CHARACTER( LEN = * ), PARAMETER :: myName="vec_set7" - REAL( DFP ), ALLOCATABLE :: localValue( : ) - INTEGER( I4B ) :: ii, jj, kk - !! +CHARACTER(*), PARAMETER :: myName = "vec_set7" +REAL(DFP), ALLOCATABLE :: localValue(:) +INTEGER(I4B) :: ii, jj, kk #ifdef DEBUG_VER - IF( .NOT. obj%isInitiated ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'Vector object is not initiated' ) - !! - IF( storageFMT .NE. FMT_DOF .AND. storageFMT .NE. FMT_NODES ) & - & CALL eVector%raiseError(modName//'::'//myName// " - "// & - & 'The value of storageFMT should be either ' & - & // trim(str(FMT_DOF,.true.)) & - & // " or " // trim( str(FMT_NODES, .true. )) ) +IF (.NOT. obj%isInitiated) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Vector object is not initiated') +IF (storageFMT .NE. FMT_DOF .AND. storageFMT .NE. FMT_NODES) & + & CALL e%raiseError(modName//'::'//myName//" - "// & + & 'The value of storageFMT should be either ' & + & //TRIM(str(FMT_DOF, .TRUE.)) & + & //" or "//TRIM(str(FMT_NODES, .TRUE.))) #endif - !! - IF( PRESENT( dofs ) ) THEN - ! check the size of val - ii = SIZE( dofs ) * SIZE( nodeNum ) - !! +IF (PRESENT(dofs)) THEN + ! check the size of val + ii = SIZE(dofs) * SIZE(nodeNum) #ifdef DEBUG_VER - IF( ii .NE. SIZE( value ) ) & - & CALL eVector%raiseError( modName//'::'//myName// " - " & - & // 'The size of val is not correct: needed ' & - & // trim( str( ii, .true. ) ) & - & // "but found : " // trim( str( SIZE( value ), .true. ) ) ) + IF (ii .NE. SIZE(VALUE)) & + & CALL e%raiseError(modName//'::'//myName//" - " & + & //'The size of val is not correct: needed ' & + & //TRIM(str(ii, .TRUE.)) & + & //"but found : "//TRIM(str(SIZE(VALUE), .TRUE.))) #endif - !! - ALLOCATE( localValue( SIZE( nodeNum ) ) ) - !! - DO ii = 1, SIZE( dofs ) - IF( storageFMT .EQ. FMT_DOF ) THEN - DO jj = 1, SIZE( nodeNum ) - kk = ( ii - 1 ) * SIZE( nodeNum ) + jj - localValue( jj ) = value( kk ) - END DO - ELSE - DO jj = 1, SIZE( nodeNum ) - kk = ( jj - 1 ) * SIZE( dofs ) + ii - localValue( jj ) = value( kk ) - END DO - END IF - CALL set( Vec=obj%realVec%val, & - & obj=obj%dof, & - & nodenum=nodeNum, & - & value=localValue, & - & idof=dofs( ii ) ) - END DO - !! - ELSE + ALLOCATE (localValue(SIZE(nodeNum))) + DO ii = 1, SIZE(dofs) + IF (storageFMT .EQ. FMT_DOF) THEN + DO jj = 1, SIZE(nodeNum) + kk = (ii - 1) * SIZE(nodeNum) + jj + localValue(jj) = VALUE(kk) + END DO + ELSE + DO jj = 1, SIZE(nodeNum) + kk = (jj - 1) * SIZE(dofs) + ii + localValue(jj) = VALUE(kk) + END DO + END IF + CALL set(Vec=obj%realVec%val, & + & obj=obj%dof, & + & nodenum=nodeNum, & + & VALUE=localValue, & + & idof=dofs(ii)) + END DO +ELSE !! check the size of val - ii = (.tdof. obj%dof) * SIZE( nodeNum ) - !! + ii = (.tdof.obj%dof) * SIZE(nodeNum) #ifdef DEBUG_VER - IF( ii .NE. SIZE( value ) ) & - & CALL eVector%raiseError( modName//'::'//myName// " - " & - & // 'The size of val is not correct: needed ' & - & // trim( str( ii, .true. ) ) & - & // "but found : " // trim( str( SIZE( value ), .true. ) ) ) + IF (ii .NE. SIZE(VALUE)) & + & CALL e%raiseError(modName//'::'//myName//" - " & + & //'The size of val is not correct: needed ' & + & //TRIM(str(ii, .TRUE.)) & + & //"but found : "//TRIM(str(SIZE(VALUE), .TRUE.))) #endif - !! - IF( storageFMT .EQ. obj%dof%storageFMT ) THEN + IF (storageFMT .EQ. obj%dof%storageFMT) THEN + CALL set(Vec=obj%realVec%val, obj=obj%dof, nodenum=nodeNum, & + & VALUE=VALUE, Conversion=[NONE]) + ELSE + IF (storageFMT .EQ. FMT_NODES) THEN CALL set(Vec=obj%realVec%val, obj=obj%dof, nodenum=nodeNum, & - & value=value, Conversion=[NONE] ) + & VALUE=VALUE, Conversion=[NodesToDOF]) ELSE - IF( storageFMT .EQ. FMT_NODES ) THEN - CALL set(Vec=obj%realVec%val, obj=obj%dof, nodenum=nodeNum, & - & value=value, Conversion=[NodesToDOF] ) - ELSE - CALL set(Vec=obj%realVec%val, obj=obj%dof, nodenum=nodeNum, & - & value=value, Conversion=[DOFtoNodes] ) - END IF + CALL set(Vec=obj%realVec%val, obj=obj%dof, nodenum=nodeNum, & + & VALUE=VALUE, Conversion=[DOFtoNodes]) END IF - !! END IF - !! +END IF END PROCEDURE vec_set7 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- - - -END SUBMODULE SetMethods \ No newline at end of file +END SUBMODULE SetMethods diff --git a/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 b/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 index 1eae83531..8f5f73347 100644 --- a/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 @@ -17,21 +17,40 @@ SUBMODULE(VectorField_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! setVectorFieldParam +! SetVectorFieldParam !---------------------------------------------------------------------------- -MODULE PROCEDURE setVectorFieldParam -INTEGER(I4B) :: ierr -ierr = param%set(key=myprefix//"/name", VALUE=TRIM(name)) -ierr = param%set(key=myprefix//"/engine", VALUE=TRIM(engine)) -ierr = param%set(key=myprefix//"/spaceCompo", VALUE=spaceCompo) -ierr = param%set(key=myprefix//"/fieldType", & - & VALUE=INPUT(default=FIELD_TYPE_NORMAL, option=fieldType)) -END PROCEDURE setVectorFieldParam +MODULE PROCEDURE SetVectorFieldParam +TYPE(ParameterList_), POINTER :: sublist + +CALL SetAbstractFieldParam( & + & param=param, & + & prefix=myprefix, & + & name=name, & + & engine=engine, & + & fieldType=fieldType, & + & comm=comm, & + & local_n=local_n, & + & global_n=global_n) + +sublist => NULL() +sublist => param%NewSubList(key=myprefix) + +CALL Set( & + & obj=sublist, & + & datatype=TypeIntI4B, & + & prefix=myprefix, & + & key="spaceCompo", & + & VALUE=spaceCompo) + +sublist => NULL() + +END PROCEDURE SetVectorFieldParam !---------------------------------------------------------------------------- ! CheckEssentialParam @@ -39,25 +58,71 @@ MODULE PROCEDURE vField_checkEssentialParam CHARACTER(*), PARAMETER :: myName = "vField_checkEssentialParam" -IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN +CALL AbstractFieldCheckEssentialParam(obj=obj, param=param, prefix=myprefix) +IF (.NOT. param%IsPresent(key=myprefix//"/spaceCompo")) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/name should be present in param') + & 'spaceCompo should be present in param.') END IF -IF (.NOT. param%isPresent(key=myprefix//"/engine")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/engine should be present in param') +END PROCEDURE vField_checkEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE vField_Initiate1 +CHARACTER(*), PARAMETER :: myName = "vField_Initiate1()" +TYPE(String) :: astr +INTEGER(I4B) :: nsd, tdof, ierr, spaceCompo, tNodes +TYPE(ParameterList_), POINTER :: sublist + +! main +sublist => NULL() + +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') END IF -IF (.NOT. param%isPresent(key=myprefix//"/spaceCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/spaceCompo should be present in param') + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') END IF -END PROCEDURE vField_checkEssentialParam + +CALL obj%CheckEssentialParam(sublist) +CALL obj%DEALLOCATE() + +CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) +CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", VALUE=spaceCompo) +tNodes = dom%GetTotalNodes() +tdof = tNodes * spaceCompo + +CALL AbstractNodeFieldSetParam(obj=obj, & + & dof_tPhysicalVars=1_I4B, & + & dof_storageFMT=NODES_FMT, & + & dof_spaceCompo=[spaceCompo], & + & dof_timeCompo=[1_I4B], & + & dof_tNodes=[tNodes], & + & dof_names_char=[astr%slice(1, 1)], & + & tSize=tdof) + +nsd = dom%GetNSD() + +CALL AbstractNodeFieldInitiate( & + & obj=obj, & + & param=param, & + & dom=dom, & + & prefix=myprefix) + +astr = "" +sublist => NULL() +END PROCEDURE vField_Initiate1 !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_Initiate1 +MODULE PROCEDURE vField_Initiate1_old CHARACTER(*), PARAMETER :: myName = "vField_Initiate" INTEGER(I4B) :: ierr, storageFMT, tNodes(1), timeCompo(1), & & spaceCompo(1) @@ -138,7 +203,7 @@ obj%isInitiated = .TRUE. IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE vField_Initiate1 +END PROCEDURE vField_Initiate1_old !---------------------------------------------------------------------------- ! Initiate @@ -179,7 +244,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE vField_Constructor1 -CALL ans%initiate(param, dom) +CALL ans%Initiate(param, dom) END PROCEDURE vField_Constructor1 !---------------------------------------------------------------------------- @@ -188,7 +253,7 @@ MODULE PROCEDURE vField_Constructor_1 ALLOCATE (ans) -CALL ans%initiate(param, dom) +CALL ans%Initiate(param, dom) END PROCEDURE vField_Constructor_1 !---------------------------------------------------------------------------- diff --git a/src/submodules/VectorMeshField/src/VectorMeshField_Class@ConstructorMethods.F90 b/src/submodules/VectorMeshField/src/VectorMeshField_Class@ConstructorMethods.F90 index 3111a168e..3f2cb38b3 100644 --- a/src/submodules/VectorMeshField/src/VectorMeshField_Class@ConstructorMethods.F90 +++ b/src/submodules/VectorMeshField/src/VectorMeshField_Class@ConstructorMethods.F90 @@ -56,7 +56,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE aField_CheckEssentialParam -CALL AbstractFieldCheckEssentialParam( & +CALL AbstractMeshFieldCheckEssentialParam( & & obj=obj, & & prefix="VectorMeshField", & & param=param) From 6109cab53422db9fb62103fcd3bce9c7f5c7327b Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 15:40:20 +0900 Subject: [PATCH 014/117] Updates in AbstractMeshField_Class --- .../AbstractFile/src/AbstractFile_Class.F90 | 203 ++-- .../FortranFile/src/FortranFile_Class.F90 | 125 +- .../TxtFile/src/ConstructorMethods.inc | 93 -- src/modules/TxtFile/src/EnquireMethods.inc | 32 - src/modules/TxtFile/src/GetMethods.inc | 73 -- src/modules/TxtFile/src/ReadMethods.inc | 292 ----- src/modules/TxtFile/src/SetMethods.inc | 47 - src/modules/TxtFile/src/TxtFile_Class.F90 | 1029 +++++++++++++++-- src/modules/TxtFile/src/WriteMethods.inc | 381 ------ .../FortranFile_Class@ConstructorMethods.F90 | 49 +- .../TxtFile/src/TxtFile_Class@ReadMethods.F90 | 41 +- 11 files changed, 1125 insertions(+), 1240 deletions(-) delete mode 100644 src/modules/TxtFile/src/ConstructorMethods.inc delete mode 100644 src/modules/TxtFile/src/EnquireMethods.inc delete mode 100644 src/modules/TxtFile/src/GetMethods.inc delete mode 100644 src/modules/TxtFile/src/ReadMethods.inc delete mode 100644 src/modules/TxtFile/src/SetMethods.inc delete mode 100644 src/modules/TxtFile/src/WriteMethods.inc diff --git a/src/modules/AbstractFile/src/AbstractFile_Class.F90 b/src/modules/AbstractFile/src/AbstractFile_Class.F90 index c344d91e1..54e114e0b 100644 --- a/src/modules/AbstractFile/src/AbstractFile_Class.F90 +++ b/src/modules/AbstractFile/src/AbstractFile_Class.F90 @@ -1,39 +1,39 @@ -! This program is a part of EASIFEM library +! 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 +! 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, +! 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 +! along with thIs program. If not, see ! !> authors: Vikas Sharma, Ph. D. ! date: 2 May 2021 ! summary: module for I/O defines the base file type object. ! -! The developement of this module is inspired from the -! `FileType_Base.F90` of Futility package. The original source is located at +! The developement of thIs module Is inspired from the +! `FileType_Base.F90` of Futility package. The original source Is located at ! https://github.com/CASL/Futility/blob/master/src/FileType_Base.F90. ! ! The original code has been modified as per the code-standard of easifem ! library. ! -! This type is an abstract type, so it has no specific implementation. It -! exists only to provide a base for the extended types. It specifies the +! ThIs type Is an abstract type, so it has no specific implementation. It +! exIsts only to provide a base for the extended types. It specifies the ! maximum lengths for the file path, name, and extension, some basic -! attributes of a file such as whether or not it is open and also if it is +! attributes of a file such as whether or not it Is open and also if it Is ! open for reading or writing are provided. Methods to interface to all ! attributes are also provided. ! -! Since this is an abstract type, it has no specific implementation so see +! Since thIs Is an abstract type, it has no specific implementation so see ! one of it's extended types for examples on how it should be used. MODULE AbstractFile_Class @@ -42,12 +42,16 @@ MODULE AbstractFile_Class USE ExceptionHandler_Class, ONLY: e IMPLICIT NONE PRIVATE -!List of Public Members +!LIst of Public Members CHARACTER(*), PARAMETER :: modName = 'AbstractFile_Class' INTEGER(I4B), PARAMETER :: maxStrLen = 256 !! TYPE(ExceptionHandler_), PRIVATE :: e !! The exception handler for the object - !! List of type bound procedures (methods) for the Base File Type object + !! LIst of type bound procedures (methods) for the Base File Type object + +PUBLIC :: AbstractFile_ +PUBLIC :: AbstractFilePointer_ +PUBLIC :: AbstractFileDeallocate !---------------------------------------------------------------------------- ! AbstractFile_ @@ -55,7 +59,7 @@ MODULE AbstractFile_Class !> authors: Vikas Sharma, Ph. D. ! date: 2 May 2021 -! summary: This is an abstract type which means it has no basic implementation +! summary: A n abstract type which means it has no basic implementation TYPE, ABSTRACT :: AbstractFile_ PRIVATE @@ -72,53 +76,50 @@ MODULE AbstractFile_Class TYPE(String) :: ext !! The extension of the file name LOGICAL(LGT) :: openstat = .FALSE. - !! Whether or not the file is open + !! Whether or not the file Is open LOGICAL(LGT) :: EOFstat = .FALSE. !! Whether or not the end of file has been reached LOGICAL(LGT) :: readstat = .FALSE. - !! Whether or not the file is open for reading + !! Whether or not the file Is open for reading LOGICAL(LGT) :: writestat = .FALSE. - !! Whether or not the file is open for writing + !! Whether or not the file Is open for writing CONTAINS PRIVATE - !! - !! ConstructorMethods - !! + ! CONSTRUCTOR:1 + ! ConstructorMethods PROCEDURE, PUBLIC, PASS(Obj) :: DEALLOCATE => AbstractFileDeallocate - !! - !! @SetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: setFilePath => aFile_setFilePath - PROCEDURE, PUBLIC, PASS(obj) :: setFileName => aFile_setFileName - PROCEDURE, PUBLIC, PASS(obj) :: setFileExt => aFile_setFileExt - PROCEDURE, PUBLIC, PASS(obj) :: setEOFstat => aFile_setEOFStat - PROCEDURE, PUBLIC, PASS(obj) :: setOpenStat => aFile_setOpenStat - PROCEDURE, PUBLIC, PASS(obj) :: setReadStat => aFile_setReadStat - PROCEDURE, PUBLIC, PASS(obj) :: setWriteStat => aFile_setWriteStat - !! - !! @GetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: getFilePath => aFile_getFilePath - PROCEDURE, PUBLIC, PASS(obj) :: getFileName => aFile_getFileName - PROCEDURE, PUBLIC, PASS(obj) :: getFileExt => aFile_getFileExt - PROCEDURE, PUBLIC, PASS(obj) :: getFileParts => aFile_getFileParts - !! - !! @EnquireMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: isOpen => aFile_isOpen - PROCEDURE, PUBLIC, PASS(obj) :: isEOF => aFile_isEOF - PROCEDURE, PUBLIC, PASS(obj) :: isRead => aFile_isRead - PROCEDURE, PUBLIC, PASS(obj) :: isWrite => aFile_isWrite - !! - !! Deferred Methods - !! + + ! Set: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(obj) :: SetFilePath => aFile_SetFilePath + PROCEDURE, PUBLIC, PASS(obj) :: SetFileName => aFile_SetFileName + PROCEDURE, PUBLIC, PASS(obj) :: SetFileExt => aFile_SetFileExt + PROCEDURE, PUBLIC, PASS(obj) :: SetEOFstat => aFile_SetEOFStat + PROCEDURE, PUBLIC, PASS(obj) :: SetOpenStat => aFile_SetOpenStat + PROCEDURE, PUBLIC, PASS(obj) :: SetReadStat => aFile_SetReadStat + PROCEDURE, PUBLIC, PASS(obj) :: SetWriteStat => aFile_SetWriteStat + + ! Get: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetFilePath => aFile_GetFilePath + PROCEDURE, PUBLIC, PASS(obj) :: GetFileName => aFile_GetFileName + PROCEDURE, PUBLIC, PASS(obj) :: GetFileExt => aFile_GetFileExt + PROCEDURE, PUBLIC, PASS(obj) :: GetFileParts => aFile_GetFileParts + + ! Get: + ! @EnquireMethods + PROCEDURE, PUBLIC, PASS(obj) :: IsOpen => aFile_IsOpen + PROCEDURE, PUBLIC, PASS(obj) :: IsEOF => aFile_IsEOF + PROCEDURE, PUBLIC, PASS(obj) :: IsRead => aFile_IsRead + PROCEDURE, PUBLIC, PASS(obj) :: IsWrite => aFile_IsWrite + + ! Set: + ! Deferred Methods PROCEDURE(aFile_open), PUBLIC, DEFERRED, PASS(obj) :: OPEN PROCEDURE(aFile_close), PUBLIC, DEFERRED, PASS(obj) :: CLOSE - PROCEDURE(aFile_delete), PUBLIC, DEFERRED, PASS(obj) :: delete + PROCEDURE(aFile_Delete), PUBLIC, DEFERRED, PASS(obj) :: Delete END TYPE AbstractFile_ -PUBLIC :: AbstractFile_ - !---------------------------------------------------------------------------- ! AbstractFilePointer_ !---------------------------------------------------------------------------- @@ -127,8 +128,6 @@ MODULE AbstractFile_Class CLASS(AbstractFile_), POINTER :: ptr => NULL() END TYPE AbstractFilePointer_ -PUBLIC :: AbstractFilePointer_ - !---------------------------------------------------------------------------- ! Dealalocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -138,16 +137,14 @@ MODULE AbstractFile_Class ! summary: Deallocate the data stored in the file INTERFACE - MODULE SUBROUTINE AbstractFileDeallocate(obj, delete) + MODULE SUBROUTINE AbstractFileDeallocate(obj, Delete) CLASS(AbstractFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete END SUBROUTINE AbstractFileDeallocate END INTERFACE -PUBLIC :: AbstractFileDeallocate - !---------------------------------------------------------------------------- -! setFilePath@SetMethods +! SetFilePath@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -155,14 +152,14 @@ END SUBROUTINE AbstractFileDeallocate ! summary: Set the path of file INTERFACE - MODULE SUBROUTINE aFile_setFilePath(obj, path) + MODULE SUBROUTINE aFile_SetFilePath(obj, path) CLASS(AbstractFile_), INTENT(INOUT) :: obj TYPE(String), INTENT(IN) :: path - END SUBROUTINE aFile_setFilePath + END SUBROUTINE aFile_SetFilePath END INTERFACE !---------------------------------------------------------------------------- -! setFileName@SetMethods +! SetFileName@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -170,14 +167,14 @@ END SUBROUTINE aFile_setFilePath ! summary: Set the file name INTERFACE - MODULE SUBROUTINE aFile_setFileName(obj, fileName) + MODULE SUBROUTINE aFile_SetFileName(obj, fileName) CLASS(AbstractFile_), INTENT(INOUT) :: obj TYPE(String), INTENT(IN) :: fileName - END SUBROUTINE aFile_setFileName + END SUBROUTINE aFile_SetFileName END INTERFACE !---------------------------------------------------------------------------- -! setFileExt@SetMethods +! SetFileExt@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -185,14 +182,14 @@ END SUBROUTINE aFile_setFileName ! summary: Set the file extension INTERFACE - MODULE SUBROUTINE aFile_setFileExt(obj, Ext) + MODULE SUBROUTINE aFile_SetFileExt(obj, Ext) CLASS(AbstractFile_), INTENT(INOUT) :: obj TYPE(String), INTENT(IN) :: Ext - END SUBROUTINE aFile_setFileExt + END SUBROUTINE aFile_SetFileExt END INTERFACE !---------------------------------------------------------------------------- -! setEOFstat@SetMethods +! SetEOFstat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -200,14 +197,14 @@ END SUBROUTINE aFile_setFileExt ! summary: Set the end of file status of file INTERFACE - MODULE SUBROUTINE aFile_setEOFstat(obj, stat) + MODULE SUBROUTINE aFile_SetEOFstat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setEOFstat + END SUBROUTINE aFile_SetEOFstat END INTERFACE !---------------------------------------------------------------------------- -! setOpenStat@SetMethods +! SetOpenStat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -215,14 +212,14 @@ END SUBROUTINE aFile_setEOFstat ! summary: Set the openStat INTERFACE - MODULE SUBROUTINE aFile_setOpenStat(obj, stat) + MODULE SUBROUTINE aFile_SetOpenStat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setOpenStat + END SUBROUTINE aFile_SetOpenStat END INTERFACE !---------------------------------------------------------------------------- -! setReadStat@SetMethods +! SetReadStat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -230,14 +227,14 @@ END SUBROUTINE aFile_setOpenStat ! summary: Set the readStat INTERFACE - MODULE SUBROUTINE aFile_setReadStat(obj, stat) + MODULE SUBROUTINE aFile_SetReadStat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setReadStat + END SUBROUTINE aFile_SetReadStat END INTERFACE !---------------------------------------------------------------------------- -! setWriteStat@SetMethods +! SetWriteStat@SetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -245,14 +242,14 @@ END SUBROUTINE aFile_setReadStat ! summary: Set the writeStat INTERFACE - MODULE SUBROUTINE aFile_setWriteStat(obj, stat) + MODULE SUBROUTINE aFile_SetWriteStat(obj, stat) CLASS(AbstractFile_), INTENT(INOUT) :: obj LOGICAL(LGT), INTENT(IN) :: stat - END SUBROUTINE aFile_setWriteStat + END SUBROUTINE aFile_SetWriteStat END INTERFACE !---------------------------------------------------------------------------- -! getFilePath@GetMethods +! GetFilePath@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -260,14 +257,14 @@ END SUBROUTINE aFile_setWriteStat ! summary: Returns the path of the file INTERFACE - MODULE FUNCTION aFile_getFilePath(obj) RESULT(path) + MODULE FUNCTION aFile_GetFilePath(obj) RESULT(path) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String) :: path - END FUNCTION aFile_getFilePath + END FUNCTION aFile_GetFilePath END INTERFACE !---------------------------------------------------------------------------- -! getFileName@GetMethods +! GetFileName@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -275,14 +272,14 @@ END FUNCTION aFile_getFilePath ! summary: Returns the name of the file INTERFACE - MODULE FUNCTION aFile_getFileName(obj) RESULT(fileName) + MODULE FUNCTION aFile_GetFileName(obj) RESULT(fileName) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String) :: fileName - END FUNCTION aFile_getFileName + END FUNCTION aFile_GetFileName END INTERFACE !---------------------------------------------------------------------------- -! getFileExt@GetMethods +! GetFileExt@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -290,14 +287,14 @@ END FUNCTION aFile_getFileName ! summary: Returns the extension of the file INTERFACE - MODULE FUNCTION aFile_getFileExt(obj) RESULT(Ext) + MODULE FUNCTION aFile_GetFileExt(obj) RESULT(Ext) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String) :: Ext - END FUNCTION aFile_getFileExt + END FUNCTION aFile_GetFileExt END INTERFACE !---------------------------------------------------------------------------- -! getFileParts@GetMethods +! GetFileParts@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -305,46 +302,46 @@ END FUNCTION aFile_getFileExt ! summary: Returns the path, filename, and extension of the file INTERFACE - MODULE PURE SUBROUTINE aFile_getFileParts(obj, path, fileName, ext) + MODULE PURE SUBROUTINE aFile_GetFileParts(obj, path, fileName, ext) CLASS(AbstractFile_), INTENT(IN) :: obj TYPE(String), INTENT(OUT) :: path TYPE(String), INTENT(OUT) :: fileName TYPE(String), INTENT(OUT) :: ext - END SUBROUTINE aFile_getFileParts + END SUBROUTINE aFile_GetFileParts END INTERFACE !---------------------------------------------------------------------------- -! isOpen@GetMethods +! IsOpen@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 8 May 2022 -! summary: Returns true if the file is open +! summary: Returns true if the file Is open INTERFACE - MODULE FUNCTION aFile_isOpen(obj) RESULT(ans) + MODULE FUNCTION aFile_IsOpen(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isOpen + END FUNCTION aFile_IsOpen END INTERFACE !---------------------------------------------------------------------------- -! isEOF@EnquireMethods +! IsEOF@EnquireMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 8 May 2022 -! summary: Returns true if the end of the file is reached +! summary: Returns true if the end of the file Is reached INTERFACE - MODULE FUNCTION aFile_isEOF(obj) RESULT(ans) + MODULE FUNCTION aFile_IsEOF(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isEOF + END FUNCTION aFile_IsEOF END INTERFACE !---------------------------------------------------------------------------- -! isRead@EnquireMethods +! IsRead@EnquireMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -352,14 +349,14 @@ END FUNCTION aFile_isEOF ! summary: Returns true if the file has read access INTERFACE - MODULE FUNCTION aFile_isRead(obj) RESULT(ans) + MODULE FUNCTION aFile_IsRead(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isRead + END FUNCTION aFile_IsRead END INTERFACE !---------------------------------------------------------------------------- -! isWrite@EnquireMethods +! IsWrite@EnquireMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -367,10 +364,10 @@ END FUNCTION aFile_isRead ! summary: Returns true if the file has write access INTERFACE - MODULE FUNCTION aFile_isWrite(obj) RESULT(ans) + MODULE FUNCTION aFile_IsWrite(obj) RESULT(ans) CLASS(AbstractFile_), INTENT(IN) :: obj LOGICAL(LGT) :: ans - END FUNCTION aFile_isWrite + END FUNCTION aFile_IsWrite END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/modules/FortranFile/src/FortranFile_Class.F90 b/src/modules/FortranFile/src/FortranFile_Class.F90 index 6c94a051f..09b3d28c4 100644 --- a/src/modules/FortranFile/src/FortranFile_Class.F90 +++ b/src/modules/FortranFile/src/FortranFile_Class.F90 @@ -39,6 +39,12 @@ MODULE FortranFile_Class CHARACTER(*), PARAMETER :: hash = "#" CHARACTER(*), PARAMETER :: comma = "," INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: FortranFile_ +PUBLIC :: FortranFilePointer_ +PUBLIC :: FortranFileInitiate +PUBLIC :: FortranFileDeallocate +PUBLIC :: FortranFileBackspace +PUBLIC :: FortranFileRewind !---------------------------------------------------------------------------- ! @@ -49,86 +55,71 @@ MODULE FortranFile_Class ! update: 2021-11-07 ! summary: Datatype for handling fortran files ! -! {!pages/FortranFile_.md!} -! -! TODO -! -! Method-1 -! - name: ReadLine(obj, aline) -! - spec: Read a line in string `aline` -! -! Method-2 -! - name: ReadLines(obj, lines()) -! - spec: Read lines in string vector lines() -! -! Reference:: [[String_Method.F90]] +!{!pages/FortranFile_.md!} TYPE, EXTENDS(AbstractFile_) :: FortranFile_ PRIVATE LOGICAL(LGT) :: initstat = .FALSE. - !! file initiated or not + !! file initiated or not INTEGER(I4B) :: unitno = -1 - !! unit number + !! unit number INTEGER(I4B) :: reclval = -1 - !! record length for direct access + !! record length for direct access LOGICAL(LGT) :: formatstat = .FALSE. - !! file is formatted or not + !! file is formatted or not LOGICAL(LGT) :: accessstat = .FALSE. - !! direct or sequential access + !! direct or sequential access LOGICAL(LGT) :: newstat = .FALSE. - !! the new status of a file + !! the new status of a file LOGICAL(LGT) :: overwrite = .FALSE. - !! replace or not + !! replace or not LOGICAL(LGT) :: padstat = .FALSE. - !! Whether or not the file is being padded + !! Whether or not the file is being padded LOGICAL(LGT) :: getNewUnit = .FALSE. CHARACTER(6) :: posopt = 'ASIS ' CHARACTER(1), PUBLIC :: comment = hash CHARACTER(1), PUBLIC :: separator = " " CHARACTER(2), PUBLIC :: delimiter = "\n" - ! + CONTAINS PRIVATE - !! + + ! CONSTRUCTOR: !! @ConstructorMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: initiate => ff_initiate + PROCEDURE, PUBLIC, PASS(Obj) :: Initiate => ff_Initiate PROCEDURE, PUBLIC, PASS(Obj) :: DEALLOCATE => ff_Deallocate FINAL :: ff_final - PROCEDURE, PUBLIC, PASS(Obj) :: OPEN => ff_open - PROCEDURE, PUBLIC, PASS(Obj) :: CLOSE => ff_close - PROCEDURE, PUBLIC, PASS(Obj) :: delete => ff_delete - PROCEDURE, PUBLIC, PASS(Obj) :: BACKSPACE => ff_backspace - PROCEDURE, PUBLIC, PASS(Obj) :: REWIND => ff_rewind - !! - !! @SetMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: setStatus => ff_setStatus - !! - !! @GetMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: getUnitNo => ff_getUnitNo - PROCEDURE, PUBLIC, PASS(Obj) :: getRecLen => ff_getRecLen - !! - !! @EnquireMethods - !! - PROCEDURE, PUBLIC, PASS(Obj) :: isFormatted => ff_isFormatted - PROCEDURE, PUBLIC, PASS(Obj) :: isDirect => ff_isDirect - PROCEDURE, PUBLIC, PASS(Obj) :: isPadded => ff_isPadded - PROCEDURE, PUBLIC, PASS(Obj) :: isNew => ff_isNew - PROCEDURE, PUBLIC, PASS(Obj) :: isOverwrite => ff_isOverwrite - PROCEDURE, PUBLIC, PASS(Obj) :: isInitiated => ff_isInitiated + PROCEDURE, PUBLIC, PASS(Obj) :: OPEN => ff_Open + PROCEDURE, PUBLIC, PASS(Obj) :: CLOSE => ff_Close + PROCEDURE, PUBLIC, PASS(Obj) :: Delete => ff_Delete + PROCEDURE, PUBLIC, PASS(Obj) :: BACKSPACE => ff_Backspace + PROCEDURE, PUBLIC, PASS(Obj) :: REWIND => ff_Rewind + + ! SET: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(Obj) :: SetStatus => ff_SetStatus + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(Obj) :: GetUnitNo => ff_GetUnitNo + PROCEDURE, PUBLIC, PASS(Obj) :: GetRecLen => ff_GetRecLen + + ! GET: + ! @EnquireMethods + PROCEDURE, PUBLIC, PASS(Obj) :: IsFormatted => ff_IsFormatted + PROCEDURE, PUBLIC, PASS(Obj) :: IsDirect => ff_IsDirect + PROCEDURE, PUBLIC, PASS(Obj) :: IsPadded => ff_IsPadded + PROCEDURE, PUBLIC, PASS(Obj) :: IsNew => ff_IsNew + PROCEDURE, PUBLIC, PASS(Obj) :: IsOverwrite => ff_IsOverwrite + PROCEDURE, PUBLIC, PASS(Obj) :: IsInitiated => ff_IsInitiated END TYPE FortranFile_ -PUBLIC :: FortranFile_ TYPE(FortranFile_), PUBLIC, PARAMETER :: TypeFortranFile = FortranFile_() TYPE :: FortranFilePointer_ CLASS(FortranFile_), POINTER :: ptr => NULL() END TYPE -PUBLIC :: FortranFilePointer_ - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -137,7 +128,7 @@ MODULE FortranFile_Class ! date: 19 July 2022 ! summary: Initiate the fortran file -INTERFACE +INTERFACE FortranFileInitiate MODULE SUBROUTINE ff_initiate(obj, filename, unit, status, access, form, & & position, action, pad, recl, comment, separator, delimiter) CLASS(FortranFile_), INTENT(INOUT) :: obj @@ -168,14 +159,8 @@ MODULE SUBROUTINE ff_initiate(obj, filename, unit, status, access, form, & CHARACTER(*), OPTIONAL, INTENT(IN) :: separator CHARACTER(*), OPTIONAL, INTENT(IN) :: delimiter END SUBROUTINE ff_initiate -END INTERFACE - -INTERFACE FortranFileInitiate - MODULE PROCEDURE ff_initiate END INTERFACE FortranFileInitiate -PUBLIC :: FortranFileInitiate - !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -184,19 +169,13 @@ END SUBROUTINE ff_initiate ! date: 19 July, 2022 ! summary: Clear the content of fortran file -INTERFACE +INTERFACE FortranFileDeallocate MODULE SUBROUTINE ff_Deallocate(obj, delete) CLASS(FortranFile_), INTENT(INOUT) :: obj LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete END SUBROUTINE ff_Deallocate -END INTERFACE - -INTERFACE FortranFileDeallocate - MODULE PROCEDURE ff_Deallocate END INTERFACE FortranFileDeallocate -PUBLIC :: FortranFileDeallocate - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -261,18 +240,12 @@ END SUBROUTINE ff_delete ! date: 19 July 2022 ! summary: Move one line back -INTERFACE +INTERFACE FortranFileBackspace MODULE SUBROUTINE ff_backspace(obj) CLASS(FortranFile_), INTENT(INOUT) :: obj END SUBROUTINE ff_backspace -END INTERFACE - -INTERFACE FortranFileBackspace - MODULE PROCEDURE ff_backspace END INTERFACE FortranFileBackspace -PUBLIC :: FortranFileBackspace - !---------------------------------------------------------------------------- ! Rewind@ConstructorMethods !---------------------------------------------------------------------------- @@ -281,18 +254,12 @@ END SUBROUTINE ff_backspace ! date: 19 July 2022 ! summary: Move to the begining -INTERFACE +INTERFACE FortranFileRewind MODULE SUBROUTINE ff_rewind(obj) CLASS(FortranFile_), INTENT(INOUT) :: obj END SUBROUTINE ff_rewind -END INTERFACE - -INTERFACE FortranFileRewind - MODULE PROCEDURE ff_rewind END INTERFACE FortranFileRewind -PUBLIC :: FortranFileRewind - !---------------------------------------------------------------------------- ! ff_setStatus@SetMethods !---------------------------------------------------------------------------- diff --git a/src/modules/TxtFile/src/ConstructorMethods.inc b/src/modules/TxtFile/src/ConstructorMethods.inc deleted file mode 100644 index a69f2dfd6..000000000 --- a/src/modules/TxtFile/src/ConstructorMethods.inc +++ /dev/null @@ -1,93 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Initiate the txt file - -INTERFACE - MODULE SUBROUTINE txt_initiate(obj, filename, unit, status, access, form, & - & position, action, pad, recl, comment, separator, delimiter) - CLASS(TxtFile_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: filename - INTEGER(I4B), OPTIONAL, INTENT(IN) :: unit - !! User specified unit number, it should not be `stdout, stdin, stderr` - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: status - !! OLD, NEW, SCRATCH, REPLACE, UNKNOWN - !! If UNKNOWN then we use REPLACE - !! Default is REPLACE - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: access - !! DIRECT, SEQUENTIAL, STREAM - !! Default is SEQUENTIAL - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: form - !! FORMATTED, UNFORMATTED - !! Default is FORMATTED - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: position - !! REWIND, APPEND, ASIS - !! Default is ASIS - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: action - !! READ, WRITE, READWRITE - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: pad - !! YES, NO - !! Default is YES - INTEGER(I4B), OPTIONAL, INTENT(IN) :: recl - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: comment - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: separator - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: delimiter - END SUBROUTINE txt_initiate -END INTERFACE - -INTERFACE TxtFileInitiate - MODULE PROCEDURE txt_initiate -END INTERFACE TxtFileInitiate - -PUBLIC :: TxtFileInitiate - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Deallocate the data - -INTERFACE - MODULE SUBROUTINE txt_Deallocate(obj, Delete) - CLASS(TxtFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete - END SUBROUTINE txt_Deallocate -END INTERFACE - -INTERFACE TxtFileDeallocate - MODULE PROCEDURE txt_Deallocate -END INTERFACE TxtFileDeallocate - -PUBLIC :: TxtFileDeallocate - -!---------------------------------------------------------------------------- -! Final@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE txt_final(obj) - TYPE(TxtFile_), INTENT(INOUT) :: obj - END SUBROUTINE txt_final -END INTERFACE diff --git a/src/modules/TxtFile/src/EnquireMethods.inc b/src/modules/TxtFile/src/EnquireMethods.inc deleted file mode 100644 index 19809751d..000000000 --- a/src/modules/TxtFile/src/EnquireMethods.inc +++ /dev/null @@ -1,32 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! isValidRecord@EnquireMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE FUNCTION txt_isValidRecord( obj, aline, ignoreComment, ignoreBlank, & - & commentSymbol ) RESULT( Ans ) - CLASS(TxtFile_), INTENT(IN) :: obj - TYPE(String), INTENT( IN ) :: aline - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - LOGICAL( LGT ) :: ans -END FUNCTION txt_isValidRecord -END INTERFACE diff --git a/src/modules/TxtFile/src/GetMethods.inc b/src/modules/TxtFile/src/GetMethods.inc deleted file mode 100644 index 01936a48a..000000000 --- a/src/modules/TxtFile/src/GetMethods.inc +++ /dev/null @@ -1,73 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! GetEchoUnit@GetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Get the echo units - -INTERFACE - MODULE PURE FUNCTION txt_getEchoUnit(obj) RESULT(ans) - CLASS(TxtFile_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION txt_getEchoUnit -END INTERFACE - -!---------------------------------------------------------------------------- -! getTotalRecords@GetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 2021-11-09 -! update: 2021-11-09 -! summary: Returns the total number of records in a file -! -! -!# Introduction -! -! This function returns the total number of records in a file -! If `ignoreComment=.TRUE.`, then the comments are ignored -! If `ignoreComment` is true, then `commentSymbol` should be given - -INTERFACE - MODULE FUNCTION txt_getTotalRecords(obj, ignoreComment, ignoreBlank, & - & commentSymbol) RESULT(Ans) - CLASS(TxtFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - INTEGER(I4B) :: ans - END FUNCTION txt_getTotalRecords -END INTERFACE - -!---------------------------------------------------------------------------- -! GetEchoStat@GetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Get the echo status - -INTERFACE - MODULE PURE FUNCTION txt_getEchoStat(obj) RESULT(ans) - CLASS(TxtFile_), INTENT(IN) :: obj - LOGICAL(LGT) :: ans - END FUNCTION txt_getEchoStat -END INTERFACE diff --git a/src/modules/TxtFile/src/ReadMethods.inc b/src/modules/TxtFile/src/ReadMethods.inc deleted file mode 100644 index 930eba2ec..000000000 --- a/src/modules/TxtFile/src/ReadMethods.inc +++ /dev/null @@ -1,292 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! ReadLine@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Read a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_read_Line(obj, val, iostat, iomsg, & - & ignoreComment, ignoreBlank, commentSymbol, separator ) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), INTENT(OUT) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: separator - END SUBROUTINE txt_read_Line -END INTERFACE - -!---------------------------------------------------------------------------- -! ReadLine@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Read a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_read_Lines(obj, val, iostat, iomsg, & - & ignoreComment, ignoreBlank, commentSymbol, separator ) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), ALLOCATABLE, INTENT(INOUT) :: val( : ) - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: separator - END SUBROUTINE txt_read_Lines -END INTERFACE - -!---------------------------------------------------------------------------- -! ReadLine@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Read a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_read_Char(obj, val, iostat, iomsg, & - & ignoreComment, ignoreBlank, commentSymbol, separator ) - CLASS(TxtFile_), INTENT(INOUT) :: obj - CHARACTER( LEN = * ), INTENT(OUT) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank - CHARACTER(len=1), OPTIONAL, INTENT(IN) :: commentSymbol - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: separator - END SUBROUTINE txt_read_Char -END INTERFACE - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a scalar integer - -#define __SUBROUTINE_NAME__ txt_read_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./ReadIntScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a scalar real value - -#define __SUBROUTINE_NAME__ txt_read_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read an integer vector - -#define __SUBROUTINE_NAME__ txt_read_vec_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a intvector - -#define __SUBROUTINE_NAME__ txt_read_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a vector of intvector - -#define __SUBROUTINE_NAME__ txt_read_vec_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a real value vector - -#define __SUBROUTINE_NAME__ txt_read_vec_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_vec_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a realvector - -#define __SUBROUTINE_NAME__ txt_read_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./ReadRealScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a vector of realvector - -#define __SUBROUTINE_NAME__ txt_read_vec_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./ReadVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read an integer matrix - -#define __SUBROUTINE_NAME__ txt_read_mat_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Read a real value vector - -#define __SUBROUTINE_NAME__ txt_read_mat_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_read_mat_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./ReadMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - diff --git a/src/modules/TxtFile/src/SetMethods.inc b/src/modules/TxtFile/src/SetMethods.inc deleted file mode 100644 index e41b861fa..000000000 --- a/src/modules/TxtFile/src/SetMethods.inc +++ /dev/null @@ -1,47 +0,0 @@ -! 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 -! - - -!---------------------------------------------------------------------------- -! SetEchoStat@SetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Set the echo status - -INTERFACE - MODULE SUBROUTINE txt_setEchoStat(obj, bool) - CLASS(TxtFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), INTENT(IN) :: bool - END SUBROUTINE txt_setEchoStat -END INTERFACE - -!---------------------------------------------------------------------------- -! SetEchoUnit@SetMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Set the echo units - -INTERFACE - MODULE SUBROUTINE txt_setEchoUnit(obj, unitno) - CLASS(TxtFile_), INTENT(INOUT) :: obj - INTEGER(I4B), INTENT(IN) :: unitno - END SUBROUTINE txt_setEchoUnit -END INTERFACE diff --git a/src/modules/TxtFile/src/TxtFile_Class.F90 b/src/modules/TxtFile/src/TxtFile_Class.F90 index 0e87d9a2e..596083660 100644 --- a/src/modules/TxtFile/src/TxtFile_Class.F90 +++ b/src/modules/TxtFile/src/TxtFile_Class.F90 @@ -26,8 +26,14 @@ MODULE TxtFile_Class USE FortranFile_Class IMPLICIT NONE PRIVATE -CHARACTER(LEN=*), PARAMETER :: modName = 'TxtFile_Class' +CHARACTER(*), PARAMETER :: modName = 'TxtFile_Class' INTEGER(I4B), PARAMETER :: maxStrLen = 256 +PUBLIC :: TxtFilePointer_ +PUBLIC :: TxtFile_ +PUBLIC :: TypeTxtFile +PUBLIC :: TxtFileInitiate +PUBLIC :: TxtFileDeallocate +PUBLIC :: TxtFileWrite !---------------------------------------------------------------------------- ! TxtFile_ @@ -46,126 +52,124 @@ MODULE TxtFile_Class PRIVATE LOGICAL(LGT) :: echostat = .FALSE. INTEGER(I4B) :: echounit = -1 - ! + CONTAINS PRIVATE - !! - !! @ConstructorMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: initiate => txt_initiate - PROCEDURE, PUBLIC, PASS(obj) :: Deallocate => txt_Deallocate + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => txt_initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => txt_Deallocate FINAL :: txt_final - !! - !! @EnquireMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: isValidRecord => txt_isValidRecord - !! - !! @SetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: setEchoStat => txt_setEchoStat - PROCEDURE, PUBLIC, PASS(obj) :: setEchoUnit => txt_setEchoUnit - !! - !! @GetMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: getEchoStat => txt_getEchoStat - PROCEDURE, PUBLIC, PASS(obj) :: getEchoUnit => txt_getEchoUnit - PROCEDURE, PUBLIC, PASS(obj) :: getTotalRecords => txt_getTotalRecords - !! - !! @ReadMethods - !! - !! read strings and chars - PROCEDURE, PUBLIC, PASS(obj) :: readLine => txt_read_Line - PROCEDURE, PUBLIC, PASS(obj) :: readLines => txt_read_Lines - PROCEDURE, PASS(obj) :: readChar => txt_read_Char + + ! GET: + ! @EnquireMethods + PROCEDURE, PUBLIC, PASS(obj) :: IsValidRecord => txt_IsValidRecord + + ! SET: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(obj) :: SetEchoStat => txt_SetEchoStat + PROCEDURE, PUBLIC, PASS(obj) :: SetEchoUnit => txt_SetEchoUnit + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetEchoStat => txt_GetEchoStat + PROCEDURE, PUBLIC, PASS(obj) :: GetEchoUnit => txt_GetEchoUnit + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalRecords => txt_GetTotalRecords + + ! IO: + ! @ReadMethods + PROCEDURE, PUBLIC, PASS(obj) :: ReadLine => txt_read_Line + !! Read strings and chars + PROCEDURE, PUBLIC, PASS(obj) :: ReadLines => txt_read_Lines + !! Read strings and chars + PROCEDURE, PASS(obj) :: ReadChar => txt_read_Char !! scalars - PROCEDURE, PASS(obj) :: readInt8 => txt_read_Int8 - PROCEDURE, PASS(obj) :: readInt16 => txt_read_Int16 - PROCEDURE, PASS(obj) :: readInt32 => txt_read_Int32 - PROCEDURE, PASS(obj) :: readInt64 => txt_read_Int64 - PROCEDURE, PASS(obj) :: readReal32 => txt_read_Real32 - PROCEDURE, PASS(obj) :: readReal64 => txt_read_Real64 + PROCEDURE, PASS(obj) :: ReadInt8 => txt_read_Int8 + PROCEDURE, PASS(obj) :: ReadInt16 => txt_read_Int16 + PROCEDURE, PASS(obj) :: ReadInt32 => txt_read_Int32 + PROCEDURE, PASS(obj) :: ReadInt64 => txt_read_Int64 + PROCEDURE, PASS(obj) :: ReadReal32 => txt_read_Real32 + PROCEDURE, PASS(obj) :: ReadReal64 => txt_read_Real64 !! vectors - PROCEDURE, PASS(obj) :: readVecInt8 => txt_read_vec_Int8 - PROCEDURE, PASS(obj) :: readVecInt16 => txt_read_vec_Int16 - PROCEDURE, PASS(obj) :: readVecInt32 => txt_read_vec_Int32 - PROCEDURE, PASS(obj) :: readVecInt64 => txt_read_vec_Int64 - PROCEDURE, PASS(obj) :: readIntVector => txt_read_IntVector - PROCEDURE, PASS(obj) :: readVecIntVector => txt_read_vec_IntVector - PROCEDURE, PASS(obj) :: readVecReal32 => txt_read_vec_Real32 - PROCEDURE, PASS(obj) :: readVecReal64 => txt_read_vec_Real64 - PROCEDURE, PASS(obj) :: readRealVector => txt_read_RealVector - PROCEDURE, PASS(obj) :: readVecRealVector => txt_read_vec_RealVector + PROCEDURE, PASS(obj) :: ReadVecInt8 => txt_read_vec_Int8 + PROCEDURE, PASS(obj) :: ReadVecInt16 => txt_read_vec_Int16 + PROCEDURE, PASS(obj) :: ReadVecInt32 => txt_read_vec_Int32 + PROCEDURE, PASS(obj) :: ReadVecInt64 => txt_read_vec_Int64 + PROCEDURE, PASS(obj) :: ReadIntVector => txt_read_IntVector + PROCEDURE, PASS(obj) :: ReadVecIntVector => txt_read_vec_IntVector + PROCEDURE, PASS(obj) :: ReadVecReal32 => txt_read_vec_Real32 + PROCEDURE, PASS(obj) :: ReadVecReal64 => txt_read_vec_Real64 + PROCEDURE, PASS(obj) :: ReadRealVector => txt_read_RealVector + PROCEDURE, PASS(obj) :: ReadVecRealVector => txt_read_vec_RealVector !! matrix - PROCEDURE, PASS(obj) :: readMatReal32 => txt_read_Mat_Real32 - PROCEDURE, PASS(obj) :: readMatReal64 => txt_read_Mat_Real64 - PROCEDURE, PASS(obj) :: readMatInt8 => txt_read_Mat_Int8 - PROCEDURE, PASS(obj) :: readMatInt16 => txt_read_Mat_Int16 - PROCEDURE, PASS(obj) :: readMatInt32 => txt_read_Mat_Int32 - PROCEDURE, PASS(obj) :: readMatInt64 => txt_read_Mat_Int64 + PROCEDURE, PASS(obj) :: ReadMatReal32 => txt_read_Mat_Real32 + PROCEDURE, PASS(obj) :: ReadMatReal64 => txt_read_Mat_Real64 + PROCEDURE, PASS(obj) :: ReadMatInt8 => txt_read_Mat_Int8 + PROCEDURE, PASS(obj) :: ReadMatInt16 => txt_read_Mat_Int16 + PROCEDURE, PASS(obj) :: ReadMatInt32 => txt_read_Mat_Int32 + PROCEDURE, PASS(obj) :: ReadMatInt64 => txt_read_Mat_Int64 !! generic - GENERIC, PUBLIC :: read => & - & readLine, readLines, readChar, & - & readInt8, readInt16, readInt32, readInt64, & - & readReal32, readReal64, & - & readVecInt8, readVecInt16, readVecInt32, readVecInt64, & - & readIntVector, readVecIntVector, & - & readVecReal32, readVecReal64, & - & readRealVector, readVecRealVector, & - & readMatInt8, readMatInt16, readMatInt32, readMatInt64, & - & readMatReal32, readMatReal64 - !! - !! @WriteMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: convertMarkdownToSource => & - & txt_convertMarkDownToSource - !! - PROCEDURE, PUBLIC, PASS(obj) :: writeBlank => txt_write_Blank - PROCEDURE, PUBLIC, PASS(obj) :: nextRow => txt_write_Blank - PROCEDURE, PUBLIC, PASS(obj) :: writeLine => txt_write_Line - PROCEDURE, PUBLIC, PASS(obj) :: writeLines => txt_write_Lines - PROCEDURE, PASS(obj) :: writeChar => txt_write_Char + GENERIC, PUBLIC :: Read => & + & ReadLine, ReadLines, ReadChar, & + & ReadInt8, ReadInt16, ReadInt32, ReadInt64, & + & ReadReal32, ReadReal64, & + & ReadVecInt8, ReadVecInt16, ReadVecInt32, ReadVecInt64, & + & ReadIntVector, ReadVecIntVector, & + & ReadVecReal32, ReadVecReal64, & + & ReadRealVector, ReadVecRealVector, & + & ReadMatInt8, ReadMatInt16, ReadMatInt32, ReadMatInt64, & + & ReadMatReal32, ReadMatReal64 + + ! IO: + ! @WriteMethods + PROCEDURE, PUBLIC, PASS(obj) :: ConvertMarkdownToSource => & + & txt_ConvertMarkDownToSource + PROCEDURE, PUBLIC, PASS(obj) :: WriteBlank => txt_write_Blank + PROCEDURE, PUBLIC, PASS(obj) :: nextRow => txt_Write_Blank + PROCEDURE, PUBLIC, PASS(obj) :: WriteLine => txt_write_Line + PROCEDURE, PUBLIC, PASS(obj) :: WriteLines => txt_write_Lines + PROCEDURE, PASS(obj) :: WriteChar => txt_write_Char !! scalars - PROCEDURE, PASS(obj) :: writeInt8 => txt_write_Int8 - PROCEDURE, PASS(obj) :: writeInt16 => txt_write_Int16 - PROCEDURE, PASS(obj) :: writeInt32 => txt_write_Int32 - PROCEDURE, PASS(obj) :: writeInt64 => txt_write_Int64 - PROCEDURE, PASS(obj) :: writeReal32 => txt_write_Real32 - PROCEDURE, PASS(obj) :: writeReal64 => txt_write_Real64 + PROCEDURE, PASS(obj) :: WriteInt8 => txt_write_Int8 + PROCEDURE, PASS(obj) :: WriteInt16 => txt_write_Int16 + PROCEDURE, PASS(obj) :: WriteInt32 => txt_write_Int32 + PROCEDURE, PASS(obj) :: WriteInt64 => txt_write_Int64 + PROCEDURE, PASS(obj) :: WriteReal32 => txt_write_Real32 + PROCEDURE, PASS(obj) :: WriteReal64 => txt_write_Real64 !! vectors - PROCEDURE, PASS(obj) :: writeVecInt8 => txt_write_vec_Int8 - PROCEDURE, PASS(obj) :: writeVecInt16 => txt_write_vec_Int16 - PROCEDURE, PASS(obj) :: writeVecInt32 => txt_write_vec_Int32 - PROCEDURE, PASS(obj) :: writeVecInt64 => txt_write_vec_Int64 - PROCEDURE, PASS(obj) :: writeIntVector => txt_write_IntVector - PROCEDURE, PASS(obj) :: writeVecIntVector => txt_write_vec_IntVector - PROCEDURE, PASS(obj) :: writeVecReal32 => txt_write_vec_Real32 - PROCEDURE, PASS(obj) :: writeVecReal64 => txt_write_vec_Real64 - PROCEDURE, PASS(obj) :: writeRealVector => txt_write_RealVector - PROCEDURE, PASS(obj) :: writeVecRealVector => txt_write_vec_RealVector + PROCEDURE, PASS(obj) :: WriteVecInt8 => txt_write_vec_Int8 + PROCEDURE, PASS(obj) :: WriteVecInt16 => txt_write_vec_Int16 + PROCEDURE, PASS(obj) :: WriteVecInt32 => txt_write_vec_Int32 + PROCEDURE, PASS(obj) :: WriteVecInt64 => txt_write_vec_Int64 + PROCEDURE, PASS(obj) :: WriteIntVector => txt_write_IntVector + PROCEDURE, PASS(obj) :: WriteVecIntVector => txt_write_vec_IntVector + PROCEDURE, PASS(obj) :: WriteVecReal32 => txt_write_vec_Real32 + PROCEDURE, PASS(obj) :: WriteVecReal64 => txt_write_vec_Real64 + PROCEDURE, PASS(obj) :: WriteRealVector => txt_write_RealVector + PROCEDURE, PASS(obj) :: WriteVecRealVector => txt_write_vec_RealVector !! matrix - PROCEDURE, PASS(obj) :: writeMatReal32 => txt_write_Mat_Real32 - PROCEDURE, PASS(obj) :: writeMatReal64 => txt_write_Mat_Real64 - PROCEDURE, PASS(obj) :: writeMatInt8 => txt_write_Mat_Int8 - PROCEDURE, PASS(obj) :: writeMatInt16 => txt_write_Mat_Int16 - PROCEDURE, PASS(obj) :: writeMatInt32 => txt_write_Mat_Int32 - PROCEDURE, PASS(obj) :: writeMatInt64 => txt_write_Mat_Int64 + PROCEDURE, PASS(obj) :: WriteMatReal32 => txt_write_Mat_Real32 + PROCEDURE, PASS(obj) :: WriteMatReal64 => txt_write_Mat_Real64 + PROCEDURE, PASS(obj) :: WriteMatInt8 => txt_write_Mat_Int8 + PROCEDURE, PASS(obj) :: WriteMatInt16 => txt_write_Mat_Int16 + PROCEDURE, PASS(obj) :: WriteMatInt32 => txt_write_Mat_Int32 + PROCEDURE, PASS(obj) :: WriteMatInt64 => txt_write_Mat_Int64 !! generic - GENERIC, PUBLIC :: write => & - & writeBlank, & - & writeLine, writeLines, writeChar, & - & writeInt8, writeInt16, writeInt32, writeInt64, & - & writeVecInt8, writeVecInt16, writeVecInt32, writeVecInt64, & - & writeMatInt8, writeMatInt16, writeMatInt32, writeMatInt64, & - & writeIntVector, writeVecIntVector, & - & writeReal32, writeReal64, & - & writeVecReal32, writeVecReal64, & - & writeRealVector, writeVecRealVector, & - & writeMatReal32, writeMatReal64 + GENERIC, PUBLIC :: Write => & + & WriteBlank, & + & WriteLine, WriteLines, WriteChar, & + & WriteInt8, WriteInt16, WriteInt32, WriteInt64, & + & WriteVecInt8, WriteVecInt16, WriteVecInt32, WriteVecInt64, & + & WriteMatInt8, WriteMatInt16, WriteMatInt32, WriteMatInt64, & + & WriteIntVector, WriteVecIntVector, & + & WriteReal32, WriteReal64, & + & WriteVecReal32, WriteVecReal64, & + & WriteRealVector, WriteVecRealVector, & + & WriteMatReal32, WriteMatReal64 END TYPE TxtFile_ -PUBLIC :: TxtFile_ - -TYPE(TxtFile_), PUBLIC, PARAMETER :: TypeTxtFile = TxtFile_() +TYPE(TxtFile_), PARAMETER :: TypeTxtFile = TxtFile_() !---------------------------------------------------------------------------- ! TxtFilePointer @@ -175,13 +179,808 @@ MODULE TxtFile_Class CLASS(TxtFile_), POINTER :: ptr => NULL() END TYPE -PUBLIC :: TxtFilePointer_ +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Initiate the txt file + +INTERFACE TxtFileInitiate + MODULE SUBROUTINE txt_initiate(obj, filename, unit, status, access, form, & + & position, action, pad, recl, comment, separator, delimiter) + CLASS(TxtFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: filename + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unit + !! User specified unit number, it should not be `stdout, stdin, stderr` + CHARACTER(*), OPTIONAL, INTENT(IN) :: status + !! OLD, NEW, SCRATCH, REPLACE, UNKNOWN + !! If UNKNOWN then we use REPLACE + !! Default is REPLACE + CHARACTER(*), OPTIONAL, INTENT(IN) :: access + !! DIRECT, SEQUENTIAL, STREAM + !! Default is SEQUENTIAL + CHARACTER(*), OPTIONAL, INTENT(IN) :: form + !! FORMATTED, UNFORMATTED + !! Default is FORMATTED + CHARACTER(*), OPTIONAL, INTENT(IN) :: position + !! REWIND, APPEND, ASIS + !! Default is ASIS + CHARACTER(*), OPTIONAL, INTENT(IN) :: action + !! READ, WRITE, READWRITE + CHARACTER(*), OPTIONAL, INTENT(IN) :: pad + !! YES, NO + !! Default is YES + INTEGER(I4B), OPTIONAL, INTENT(IN) :: recl + CHARACTER(*), OPTIONAL, INTENT(IN) :: comment + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + CHARACTER(*), OPTIONAL, INTENT(IN) :: delimiter + END SUBROUTINE txt_initiate +END INTERFACE TxtFileInitiate + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Deallocate the data + +INTERFACE TxtFileDeallocate + MODULE SUBROUTINE txt_Deallocate(obj, Delete) + CLASS(TxtFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: Delete + END SUBROUTINE txt_Deallocate +END INTERFACE TxtFileDeallocate + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE txt_final(obj) + TYPE(TxtFile_), INTENT(INOUT) :: obj + END SUBROUTINE txt_final +END INTERFACE + +!---------------------------------------------------------------------------- +! isValidRecord@EnquireMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION txt_isValidRecord(obj, aline, ignoreComment, ignoreBlank, & + & commentSymbol) RESULT(Ans) + CLASS(TxtFile_), INTENT(IN) :: obj + TYPE(String), INTENT(IN) :: aline + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + LOGICAL(LGT) :: ans + END FUNCTION txt_isValidRecord +END INTERFACE + +!---------------------------------------------------------------------------- +! SetEchoStat@SetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Set the echo status + +INTERFACE + MODULE SUBROUTINE txt_setEchoStat(obj, bool) + CLASS(TxtFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: bool + END SUBROUTINE txt_setEchoStat +END INTERFACE + +!---------------------------------------------------------------------------- +! SetEchoUnit@SetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Set the echo units + +INTERFACE + MODULE SUBROUTINE txt_setEchoUnit(obj, unitno) + CLASS(TxtFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: unitno + END SUBROUTINE txt_setEchoUnit +END INTERFACE + +!---------------------------------------------------------------------------- +! GetEchoUnit@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Get the echo units + +INTERFACE + MODULE PURE FUNCTION txt_getEchoUnit(obj) RESULT(ans) + CLASS(TxtFile_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION txt_getEchoUnit +END INTERFACE + +!---------------------------------------------------------------------------- +! getTotalRecords@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2021-11-09 +! update: 2021-11-09 +! summary: Returns the total number of records in a file +! +! +!# Introduction +! +! This function returns the total number of records in a file +! If `ignoreComment=.TRUE.`, then the comments are ignored +! If `ignoreComment` is true, then `commentSymbol` should be given + +INTERFACE + MODULE FUNCTION txt_getTotalRecords(obj, ignoreComment, ignoreBlank, & + & commentSymbol) RESULT(Ans) + CLASS(TxtFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + INTEGER(I4B) :: ans + END FUNCTION txt_getTotalRecords +END INTERFACE + +!---------------------------------------------------------------------------- +! GetEchoStat@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Get the echo status + +INTERFACE + MODULE PURE FUNCTION txt_getEchoStat(obj) RESULT(ans) + CLASS(TxtFile_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + END FUNCTION txt_getEchoStat +END INTERFACE + +!---------------------------------------------------------------------------- +! ReadLine@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Read a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_read_Line(obj, val, iostat, iomsg, & + & ignoreComment, ignoreBlank, commentSymbol, separator) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(OUT) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + END SUBROUTINE txt_read_Line +END INTERFACE + +!---------------------------------------------------------------------------- +! ReadLine@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Read a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_read_Lines(obj, val, iostat, iomsg, & + & ignoreComment, ignoreBlank, commentSymbol, separator) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), ALLOCATABLE, INTENT(INOUT) :: val(:) + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + END SUBROUTINE txt_read_Lines +END INTERFACE + +!---------------------------------------------------------------------------- +! ReadLine@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Read a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_read_Char(obj, val, iostat, iomsg, & + & ignoreComment, ignoreBlank, commentSymbol, separator) + CLASS(TxtFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(OUT) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreComment + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: ignoreBlank + CHARACTER(1), OPTIONAL, INTENT(IN) :: commentSymbol + CHARACTER(*), OPTIONAL, INTENT(IN) :: separator + END SUBROUTINE txt_read_Char +END INTERFACE + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a scalar integer + +#define __SUBROUTINE_NAME__ txt_read_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./ReadIntScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a scalar real value + +#define __SUBROUTINE_NAME__ txt_read_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read an integer vector + +#define __SUBROUTINE_NAME__ txt_read_vec_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a intvector + +#define __SUBROUTINE_NAME__ txt_read_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a vector of intvector + +#define __SUBROUTINE_NAME__ txt_read_vec_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a real value vector + +#define __SUBROUTINE_NAME__ txt_read_vec_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_vec_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a realvector + +#define __SUBROUTINE_NAME__ txt_read_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./ReadRealScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a vector of realvector + +#define __SUBROUTINE_NAME__ txt_read_vec_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./ReadVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read an integer matrix + +#define __SUBROUTINE_NAME__ txt_read_mat_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Read a real value vector + +#define __SUBROUTINE_NAME__ txt_read_mat_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_read_mat_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./ReadMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +!---------------------------------------------------------------------------- +! ConvertMarkdownToSource@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2021-11-07 +! update: 2021-11-07 +! summary: Reads a markdown file and converts it into the source file + +INTERFACE + MODULE SUBROUTINE txt_convertMarkdownToSource(obj, outfile, lang) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(TxtFile_), INTENT(INOUT) :: outfile + CHARACTER(*), OPTIONAL, INTENT(IN) :: lang + END SUBROUTINE txt_convertMarkdownToSource +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Blank(obj) + CLASS(TxtFile_), INTENT(INOUT) :: obj + !! YES or NO + END SUBROUTINE txt_write_Blank +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Line(obj, val, iostat, iomsg, advance) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + CHARACTER(*), OPTIONAL, INTENT(IN) :: advance + !! YES or NO + END SUBROUTINE txt_write_Line +END INTERFACE + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Line +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Lines(obj, val, iostat, iomsg, advance) + CLASS(TxtFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: val(:) + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + CHARACTER(*), OPTIONAL, INTENT(IN) :: advance + !! YES, NO + END SUBROUTINE txt_write_Lines +END INTERFACE + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Lines +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! WriteLine@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 19 July 2022 +! summary: Write a single line (record) + +INTERFACE + MODULE SUBROUTINE txt_write_Char(obj, val, iostat, iomsg, & + & advance) + CLASS(TxtFile_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: val + INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat + CHARACTER(*), OPTIONAL, INTENT(OUT) :: iomsg + CHARACTER(*), OPTIONAL, INTENT(IN) :: advance + !! YES, NO + END SUBROUTINE txt_write_Char +END INTERFACE + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Char +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! Write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write an integer + +#define __SUBROUTINE_NAME__ txt_write_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Int8, txt_write_Int16, txt_write_Int32, & + & txt_write_Int64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a real value + +#define __SUBROUTINE_NAME__ txt_write_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_Real32, txt_write_Real64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! Write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write an integer vector + +#define __SUBROUTINE_NAME__ txt_write_vec_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_Int8, & + & txt_write_vec_Int16, & + & txt_write_vec_Int32, & + & txt_write_vec_Int64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a intvector + +#define __SUBROUTINE_NAME__ txt_write_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_IntVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a vector of intvector + +#define __SUBROUTINE_NAME__ txt_write_vec_IntVector +#define __DATA_TYPE__ TYPE( IntVector_ ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_IntVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a real value vector + +#define __SUBROUTINE_NAME__ txt_write_vec_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_vec_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_Real32, txt_write_vec_Real64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a RealVector + +#define __SUBROUTINE_NAME__ txt_write_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./WriteScalar.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_RealVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! read@ReadMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a vector of RealVector + +#define __SUBROUTINE_NAME__ txt_write_vec_RealVector +#define __DATA_TYPE__ TYPE( RealVector_ ) +#include "./WriteVector.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_vec_RealVector +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! Write@WriteMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write an integer matrix + +#define __SUBROUTINE_NAME__ txt_write_mat_Int8 +#define __DATA_TYPE__ INTEGER( Int8 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Int16 +#define __DATA_TYPE__ INTEGER( Int16 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Int32 +#define __DATA_TYPE__ INTEGER( Int32 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Int64 +#define __DATA_TYPE__ INTEGER( Int64 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_mat_Int8, & + & txt_write_mat_Int16, & + & txt_write_mat_Int32, & + & txt_write_mat_Int64 +END INTERFACE TxtFileWrite + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 20 July 2022 +! summary: Write a real value vector + +#define __SUBROUTINE_NAME__ txt_write_mat_Real32 +#define __DATA_TYPE__ REAL( Real32 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ + +#define __SUBROUTINE_NAME__ txt_write_mat_Real64 +#define __DATA_TYPE__ REAL( Real64 ) +#include "./WriteMatrix.inc" +#undef __SUBROUTINE_NAME__ +#undef __DATA_TYPE__ -#include "./ConstructorMethods.inc" -#include "./EnquireMethods.inc" -#include "./SetMethods.inc" -#include "./GetMethods.inc" -#include "./ReadMethods.inc" -#include "./WriteMethods.inc" +INTERFACE TxtFileWrite + MODULE PROCEDURE txt_write_mat_Real32, & + & txt_write_mat_Real64 +END INTERFACE TxtFileWrite END MODULE TxtFile_Class diff --git a/src/modules/TxtFile/src/WriteMethods.inc b/src/modules/TxtFile/src/WriteMethods.inc deleted file mode 100644 index 7caf2546a..000000000 --- a/src/modules/TxtFile/src/WriteMethods.inc +++ /dev/null @@ -1,381 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! ConvertMarkdownToSource@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 2021-11-07 -! update: 2021-11-07 -! summary: Reads a markdown file and converts it into the source file - -INTERFACE - MODULE SUBROUTINE txt_convertMarkdownToSource(obj, outfile, lang) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(TxtFile_), INTENT(INOUT) :: outfile - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: lang - END SUBROUTINE txt_convertMarkdownToSource -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Blank(obj) - CLASS(TxtFile_), INTENT(INOUT) :: obj - !! YES or NO - END SUBROUTINE txt_write_Blank -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Line(obj, val, iostat, iomsg, advance) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), INTENT(IN) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: advance - !! YES or NO - END SUBROUTINE txt_write_Line -END INTERFACE - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Line -END INTERFACE TxtFileWrite - -PUBLIC :: TxtFileWrite - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Lines(obj, val, iostat, iomsg, advance) - CLASS(TxtFile_), INTENT(INOUT) :: obj - TYPE(String), INTENT(IN) :: val(:) - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: advance - !! YES, NO - END SUBROUTINE txt_write_Lines -END INTERFACE - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Lines -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! WriteLine@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 19 July 2022 -! summary: Write a single line (record) - -INTERFACE - MODULE SUBROUTINE txt_write_Char(obj, val, iostat, iomsg, & - & advance) - CLASS(TxtFile_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: val - INTEGER(I4B), OPTIONAL, INTENT(OUT) :: iostat - CHARACTER(LEN=*), OPTIONAL, INTENT(OUT) :: iomsg - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: advance - !! YES, NO - END SUBROUTINE txt_write_Char -END INTERFACE - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Char -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! Write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write an integer - -#define __SUBROUTINE_NAME__ txt_write_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Int8, txt_write_Int16, txt_write_Int32, & - & txt_write_Int64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a real value - -#define __SUBROUTINE_NAME__ txt_write_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_Real32, txt_write_Real64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! Write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write an integer vector - -#define __SUBROUTINE_NAME__ txt_write_vec_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_Int8, & - & txt_write_vec_Int16, & - & txt_write_vec_Int32, & - & txt_write_vec_Int64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a intvector - -#define __SUBROUTINE_NAME__ txt_write_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_IntVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a vector of intvector - -#define __SUBROUTINE_NAME__ txt_write_vec_IntVector -#define __DATA_TYPE__ TYPE( IntVector_ ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_IntVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a real value vector - -#define __SUBROUTINE_NAME__ txt_write_vec_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_vec_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_Real32, txt_write_vec_Real64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a RealVector - -#define __SUBROUTINE_NAME__ txt_write_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./WriteScalar.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_RealVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! read@ReadMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a vector of RealVector - -#define __SUBROUTINE_NAME__ txt_write_vec_RealVector -#define __DATA_TYPE__ TYPE( RealVector_ ) -#include "./WriteVector.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_vec_RealVector -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! Write@WriteMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write an integer matrix - -#define __SUBROUTINE_NAME__ txt_write_mat_Int8 -#define __DATA_TYPE__ INTEGER( Int8 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Int16 -#define __DATA_TYPE__ INTEGER( Int16 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Int32 -#define __DATA_TYPE__ INTEGER( Int32 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Int64 -#define __DATA_TYPE__ INTEGER( Int64 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_mat_Int8, & - & txt_write_mat_Int16, & - & txt_write_mat_Int32, & - & txt_write_mat_Int64 -END INTERFACE TxtFileWrite - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 20 July 2022 -! summary: Write a real value vector - -#define __SUBROUTINE_NAME__ txt_write_mat_Real32 -#define __DATA_TYPE__ REAL( Real32 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -#define __SUBROUTINE_NAME__ txt_write_mat_Real64 -#define __DATA_TYPE__ REAL( Real64 ) -#include "./WriteMatrix.inc" -#undef __SUBROUTINE_NAME__ -#undef __DATA_TYPE__ - -INTERFACE TxtFileWrite - MODULE PROCEDURE txt_write_mat_Real32, & - & txt_write_mat_Real64 -END INTERFACE TxtFileWrite - diff --git a/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 b/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 index fb3df8ecc..8f98b273d 100644 --- a/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 +++ b/src/submodules/FortranFile/src/FortranFile_Class@ConstructorMethods.F90 @@ -18,8 +18,8 @@ SUBMODULE(FortranFile_Class) ConstructorMethods USE BaseMethod IMPLICIT NONE -CHARACTER(maxStrLen) :: emesg, iomsg -INTEGER(I4B) :: ioerr +! CHARACTER(maxStrLen) :: emesg, iomsg +! INTEGER(I4B) :: ioerr CONTAINS !---------------------------------------------------------------------------- @@ -36,6 +36,9 @@ TYPE(String) :: fpath, fname, fext, file_ LOGICAL(LGT) :: ostat INTEGER(I4B) :: oldcnt, ierr + +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr ! ! Initialize data ! @@ -317,6 +320,9 @@ MODULE PROCEDURE ff_Deallocate LOGICAL(LGT) :: bool +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr + !Close the file bool = .FALSE. IF (PRESENT(delete)) bool = delete @@ -366,6 +372,8 @@ CHARACTER(3) :: padvar INTEGER(I4B) :: reclval TYPE(String) :: path, filename, ext +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr !Get the appropriate clause values for the OPEN statement IF (obj%initstat) THEN @@ -510,6 +518,8 @@ MODULE PROCEDURE ff_close CHARACTER(*), PARAMETER :: myName = 'ff_close' +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr ! IF (obj%initstat) THEN IF (obj%isOpen()) THEN @@ -539,6 +549,8 @@ MODULE PROCEDURE ff_delete CHARACTER(*), PARAMETER :: myName = 'ff_delete' TYPE(String) :: path, filename, ext +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr IF (obj%initstat) THEN IF (obj%isOpen()) THEN @@ -590,6 +602,9 @@ MODULE PROCEDURE ff_backspace CHARACTER(*), PARAMETER :: myName = 'ff_backspace' +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr + IF (obj%initstat) THEN IF (obj%isOpen()) THEN BACKSPACE (UNIT=obj%unitno, IOSTAT=ioerr, IOMSG=iomsg) @@ -617,15 +632,37 @@ MODULE PROCEDURE ff_rewind CHARACTER(*), PARAMETER :: myName = 'ff_rewind' +CHARACTER(maxStrLen) :: emesg, iomsg +INTEGER(I4B) :: ioerr + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName //'::'//myName// ' - '// & + & '[START] Rewind()') +#endif + +#ifdef Darwin_SYSTEM +CALL e%RaiseError(modName //'::'//myName// ' - '// & + & '[BUG] :: REWIND() function does not work with GNU Fortran. ' // & + & 'We are working on this issue. ') +#else + IF (obj%initstat) THEN IF (obj%isOpen()) THEN + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[1] ' // tostring(obj%unitno) ) REWIND (UNIT=obj%unitno, IOSTAT=ioerr, IOMSG=iomsg) + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[2]') CALL obj%setEOFstat(.FALSE.) + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[3]') IF (ioerr /= 0) THEN WRITE (emesg, '(a,i4,a,i4,a)') 'Error rewinding file (UNIT=', & & obj%unitno, ') IOSTAT=', ioerr, ' IOMSG='//TRIM(iomsg) CALL e%raiseError(modName//'::'//myName//' - '//emesg) END IF + CALL e%RaiseDebug(modName //'::'//myName// ' - '// & + & '[4]') ELSE WRITE (emesg, '(a,i4,a)') 'Cannot rewind file (UNIT=', obj%unitno, & & '). File not is not open!' @@ -635,6 +672,14 @@ CALL e%raiseError(modName//'::'//myName//' - '// & & 'Cannot rewind file! File object has not been initialized!') END IF + +#endif + + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName //'::'//myName// ' - '// & + & '[END] Rewind()') +#endif END PROCEDURE ff_rewind !---------------------------------------------------------------------------- diff --git a/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 b/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 index 12d92b0f6..b37f968eb 100644 --- a/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 +++ b/src/submodules/TxtFile/src/TxtFile_Class@ReadMethods.F90 @@ -29,65 +29,60 @@ CHARACTER(*), PARAMETER :: myName = 'txt_read_Line' CHARACTER(maxStrLen) :: buffer INTEGER(I4B) :: buffer_size, eioerr, ioerr -! + ioerr = 0 val = "" -! + IF (obj%isOpen() .AND. .NOT. obj%isEOF()) THEN - ! + DO WHILE (ioerr .NE. IOSTAT_EOR .AND. ioerr .NE. IOSTAT_END) - ! + ! Repeatedly read chunks of current input ! file line into buffer - ! READ ( & & UNIT=obj%getUnitNo(), & & FMT='(a)', & & SIZE=buffer_size, & & ADVANCE='NO', & & IOSTAT=ioerr) buffer - ! + IF (ioerr .EQ. IOSTAT_END) THEN - ! ! end of file - ! CALL obj%setEOFstat(.TRUE.) - ! ! Done reading line. Append last buffer to line. - ! + ELSEIF (ioerr .EQ. IOSTAT_EOR) THEN - ! val = val//TRIM(buffer) - ! + IF (obj%echostat) THEN - ! + WRITE (UNIT=obj%echounit, FMT='(a)', IOSTAT=eioerr) & & TRIM(val%chars()) - ! + IF (eioerr .NE. 0) THEN CALL e%raiseError(modName//'::'//myName//" - "// & &' - Error echoing line to UNIT='//tostring(obj%echounit)//& & ' (IOSTAT='//tostring(eioerr)//')!') END IF - ! + END IF - ! + val = TRIM(val) - ! + ELSEIF (ioerr .LT. IOSTAT_EOR) THEN - ! + ! Error reading line from input file - ! + CALL e%raiseError(modName//'::'//myName//" - "// & & ' - Error reading one line from input file (IOSTAT='// & & tostring(ioerr)//')!') - ! + ELSE - ! + ! Still reading current line. Append buffer to line - ! + val = val//buffer - ! + END IF END DO END IF From 2299ac541803abb4b38e9feaef38917eb25dd8d9 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 17:02:09 +0900 Subject: [PATCH 015/117] Fixes Error in compilation related to Toml Fixes #181 --- .gitignore | 1 - .../Toml/src/include/ReadMatrix.inc | 86 +++++++++++++++++++ .../Toml/src/include/ReadVector.inc | 72 ++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 src/submodules/Toml/src/include/ReadMatrix.inc create mode 100644 src/submodules/Toml/src/include/ReadVector.inc diff --git a/.gitignore b/.gitignore index 0f33d3b23..6d084b7ac 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,6 @@ vscode-settings media/ -include/ lib/ opt/ bin/ diff --git a/src/submodules/Toml/src/include/ReadMatrix.inc b/src/submodules/Toml/src/include/ReadMatrix.inc new file mode 100644 index 000000000..4549ea737 --- /dev/null +++ b/src/submodules/Toml/src/include/ReadMatrix.inc @@ -0,0 +1,86 @@ +! 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 + + CHARACTER(*), PARAMETER :: myName = "toml_get" + TYPE(toml_array), POINTER :: array, row_array + INTEGER(I4B) :: tcol, trow, stat0, iostat, ii, tcol_same, jj + TYPE(String) :: filename + TYPE(TxtFile_) :: atxtfile + CHARACTER(512) :: iomsg + LOGICAL(LGT) :: isFound0, bool1 + + isFound0 = .FALSE. + ! try to read from the array + array => NULL() + CALL toml_get(table, key, array, & + & origin=origin, stat=stat, requested=.FALSE.) + + IF (ASSOCIATED(array)) THEN + trow = toml_len(array) + DO ii = 1, trow + row_array => NULL() + CALL toml_get(array, ii, row_array) + IF (.NOT. ASSOCIATED(row_array)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: While reading 2D array, '// & + & ' it is seems the '//tostring(ii)//'th row is empty '// & + & '(cannot read it).') + END IF + + tcol = toml_len(row_array) + IF (ii .EQ. 1) THEN + tcol_same = tcol + CALL Reallocate(VALUE, trow, tcol) + isFound0 = .TRUE. + ELSE + IF (tcol .NE. tcol_same) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Staggered matrix is not allowed') + END IF + END IF + + DO jj = 1, tcol + CALL toml_get(row_array, jj, VALUE(ii, jj)) + END DO + END DO + END IF + + ! try to read from the file + CALL toml_get(table, key, filename%raw, origin=origin, stat=stat0) + + IF (PRESENT(stat)) stat = stat0 + + IF (stat0 .EQ. toml_stat%success) THEN + CALL atxtfile%Initiate(filename=filename%Chars(), & + & action="READ", status="OLD") + CALL atxtfile%OPEN() + CALL atxtfile%READ(val=VALUE, iostat=iostat, iomsg=iomsg) + bool1 = iostat .NE. 0 .AND. (.NOT. atxtfile%isEOF()) + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error while reading txtfile, errmsg= '// & + & CHAR_LF//TRIM(iomsg)) + IF (PRESENT(isFound)) isFound = isFound0 + RETURN + END IF + isFound0 = .TRUE. + CALL atxtfile%DEALLOCATE() + END IF + + IF (PRESENT(isFound)) isFound = isFound0 + + filename = "" + NULLIFY (array) diff --git a/src/submodules/Toml/src/include/ReadVector.inc b/src/submodules/Toml/src/include/ReadVector.inc new file mode 100644 index 000000000..597d27018 --- /dev/null +++ b/src/submodules/Toml/src/include/ReadVector.inc @@ -0,0 +1,72 @@ +! 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 + + CHARACTER(*), PARAMETER :: myName = "toml_get" + TYPE(toml_array), POINTER :: array + INTEGER(I4B) :: tsize, stat0, iostat, ii + TYPE(String) :: filename + TYPE(TxtFile_) :: atxtfile + CHARACTER(512) :: iomsg + LOGICAL(LGT) :: isFound0, bool1 + + isFound0 = .FALSE. + + ! try to read from the array + array => NULL() + CALL toml_get(table, key, array, & + & origin=origin, stat=stat0, requested=.FALSE.) + + IF (ASSOCIATED(array)) THEN + tsize = toml_len(array) + CALL Reallocate(VALUE, tsize) + isFound0 = .TRUE. + DO ii = 1, tsize + CALL toml_get(array, ii, VALUE(ii)) + END DO + + IF (PRESENT(stat)) stat = stat0 + IF (PRESENT(isFound)) isFound = isFound0 + NULLIFY (array) + RETURN + END IF + + ! try to read from the file + CALL toml_get(table, key, filename%raw, origin=origin, stat=stat0) + + IF (stat0 .EQ. toml_stat%success) THEN + CALL atxtfile%Initiate(filename=filename%Chars(), & + & action="READ", status="OLD") + CALL atxtfile%OPEN() + CALL atxtfile%READ(val=VALUE, iostat=iostat, iomsg=iomsg) + + bool1 = iostat .NE. 0 .AND. (.NOT. atxtfile%isEOF()) + IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error while reading txtfile, errmsg= '// & + & CHAR_LF//TRIM(iomsg)) + IF (PRESENT(isFound)) isFound = isFound0 + IF (PRESENT(stat)) stat = stat0 + filename = "" + RETURN + END IF + + isFound0 = .TRUE. + CALL atxtfile%DEALLOCATE() + END IF + + IF (PRESENT(isFound)) isFound = isFound0 + IF (PRESENT(stat)) stat = stat0 + filename = "" From 6a8fb9968766a82532dd8d1f7dee0abd9d6832b7 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 17:22:40 +0900 Subject: [PATCH 016/117] Build error when USE_GMSH_SDK off Fixes #183 --- src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 b/src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 index 0803e0b56..bb6161b7b 100644 --- a/src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 +++ b/src/modules/GmshAPI/src/NoGmsh/Gmsh_Class.F90 @@ -27,7 +27,7 @@ END MODULE Gmsh_Class ! !---------------------------------------------------------------------------- -MODULE GmshStructuredGrid_Class +MODULE GmshStructuredMesh_Class IMPLICIT NONE -END MODULE GmshStructuredGrid_Class +END MODULE GmshStructuredMesh_Class From 1eecb0e3b35e7e7f27215deb57ab5e4e2a6aa80d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 19:27:47 +0900 Subject: [PATCH 017/117] Fixing Bug in AbstractField Fixes #186 --- .../UserFunction/src/UserFunction_Class.F90 | 33 ++++++++++++++++++- .../src/AbstractField_Class@Methods.F90 | 18 ++++++---- .../UserFunction_Class@ConstructorMethods.F90 | 8 +++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/modules/UserFunction/src/UserFunction_Class.F90 b/src/modules/UserFunction/src/UserFunction_Class.F90 index c4670a3c7..ae8904928 100644 --- a/src/modules/UserFunction/src/UserFunction_Class.F90 +++ b/src/modules/UserFunction/src/UserFunction_Class.F90 @@ -67,6 +67,8 @@ MODULE UserFunction_Class TYPE :: UserFunction_ PRIVATE + TYPE(String) :: name + !! name of the function LOGICAL(LGT) :: isInitiated = .FALSE. LOGICAL(LGT) :: isUserFunctionSet = .FALSE. LOGICAL(LGT) :: isLuaScript = .FALSE. @@ -99,18 +101,30 @@ MODULE UserFunction_Class & NULL() !! matrix function pointer CONTAINS + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & auf_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => auf_Deallocate FINAL :: auf_Final PROCEDURE, PUBLIC, PASS(obj) :: Initiate => auf_Initiate + + ! SET: + ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: Set => auf_Set1 + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetScalarValue => auf_GetScalarValue PROCEDURE, PUBLIC, PASS(obj) :: GetVectorValue => auf_GetVectorValue PROCEDURE, PUBLIC, PASS(obj) :: GetMatrixValue => auf_GetMatrixValue GENERIC, PUBLIC :: Get => GetScalarValue, GetVectorValue, GetMatrixValue PROCEDURE, PUBLIC, PASS(obj) :: GetArgType => auf_GetArgType PROCEDURE, PUBLIC, PASS(obj) :: GetReturnType => auf_GetReturnType + PROCEDURE, PUBLIC, PASS(obj) :: GetName => auf_GetName + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => auf_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => auf_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => auf_Export @@ -185,9 +199,11 @@ END SUBROUTINE auf_CheckEssentialParam ! summary: Sets user funciton parameter INTERFACE - MODULE SUBROUTINE SetUserFunctionParam(param, returnType, argType, & + MODULE SUBROUTINE SetUserFunctionParam(param, name, returnType, argType, & & numArgs, numReturns, luaScript, luaFunctionName, returnShape) TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: name + !! name INTEGER(I4B), INTENT(IN) :: returnType !! Scalar, Vector, Matrix INTEGER(I4B), INTENT(IN) :: argType @@ -327,6 +343,21 @@ MODULE PURE FUNCTION auf_GetReturnType(obj) RESULT(ans) END FUNCTION auf_GetReturnType END INTERFACE +!---------------------------------------------------------------------------- +! GetName@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-23 +! summary: Returns name of UserFunction + +INTERFACE + MODULE PURE FUNCTION auf_GetName(obj) RESULT(ans) + CLASS(UserFunction_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION auf_GetName +END INTERFACE + !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 index 096fc12ed..67115abe4 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 @@ -56,16 +56,22 @@ MODULE PROCEDURE SetAbstractFieldParam TYPE(ParameterList_), POINTER :: sublist INTEGER(I4B) :: ierr -CHARACTER(*), PARAMETER :: myName="SetAbstractFieldParam()" +CHARACTER(*), PARAMETER :: myName = "SetAbstractFieldParam()" +LOGICAL(LGT) :: isSublist sublist => NULL() -ierr = param%GetSubList(key=prefix, sublist=sublist) -sublist => param%NewSubList(key=prefix) +! Create a new sublist +isSublist = param%isSubList(prefix) -IF (ierr .NE. 0_I4B) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & +IF (isSublist) THEN + ierr = param%GetSubList(key=prefix, sublist=sublist) + IF (ierr .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + END IF +ELSE + sublist => param%NewSubList(key=prefix) END IF IF (.NOT. ASSOCIATED(sublist)) THEN @@ -172,7 +178,7 @@ ! NOTE: We should not call deallocate in abstract classes. ! This is because, in concrete classes we may set some ! parameters before calling this method. -! All those parameters will be gone if we call deallocate +! All those parameters will be gone if we call deallocate ! here. ! CALL obj%DEALLOCATE() diff --git a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 index 68f03466d..a04825aa2 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 @@ -21,6 +21,14 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! GetName +!---------------------------------------------------------------------------- + +MODULE PROCEDURE auf_GetName + ans = obj%name%chars() +END PROCEDURE auf_GetName + !---------------------------------------------------------------------------- ! UserFunctionGetReturnType !---------------------------------------------------------------------------- From 595e5bd2a001d5e7cb01f4ad51ee1d44856d58b1 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 21:57:42 +0900 Subject: [PATCH 018/117] Toml support in UserFunction_ Fixes #180 --- .../UserFunction/src/UserFunction_Class.F90 | 43 +++++++- .../Toml/src/include/ReadMatrix.inc | 20 +++- .../UserFunction_Class@ConstructorMethods.F90 | 8 +- .../src/UserFunction_Class@GetMethods.F90 | 8 ++ .../src/UserFunction_Class@IOMethods.F90 | 104 +++++++++++++----- .../src/UserFunction_Class@SetMethods.F90 | 18 +-- 6 files changed, 157 insertions(+), 44 deletions(-) diff --git a/src/modules/UserFunction/src/UserFunction_Class.F90 b/src/modules/UserFunction/src/UserFunction_Class.F90 index c4670a3c7..81a006989 100644 --- a/src/modules/UserFunction/src/UserFunction_Class.F90 +++ b/src/modules/UserFunction/src/UserFunction_Class.F90 @@ -67,6 +67,8 @@ MODULE UserFunction_Class TYPE :: UserFunction_ PRIVATE + TYPE(String) :: name + !! name of the function LOGICAL(LGT) :: isInitiated = .FALSE. LOGICAL(LGT) :: isUserFunctionSet = .FALSE. LOGICAL(LGT) :: isLuaScript = .FALSE. @@ -99,28 +101,49 @@ MODULE UserFunction_Class & NULL() !! matrix function pointer CONTAINS + PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & auf_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => auf_Deallocate FINAL :: auf_Final PROCEDURE, PUBLIC, PASS(obj) :: Initiate => auf_Initiate + + ! SET: + ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: Set => auf_Set1 + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetScalarValue => auf_GetScalarValue PROCEDURE, PUBLIC, PASS(obj) :: GetVectorValue => auf_GetVectorValue PROCEDURE, PUBLIC, PASS(obj) :: GetMatrixValue => auf_GetMatrixValue GENERIC, PUBLIC :: Get => GetScalarValue, GetVectorValue, GetMatrixValue PROCEDURE, PUBLIC, PASS(obj) :: GetArgType => auf_GetArgType PROCEDURE, PUBLIC, PASS(obj) :: GetReturnType => auf_GetReturnType + PROCEDURE, PUBLIC, PASS(obj) :: GetName => auf_GetName + !! Get name of the function + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => auf_Display + !! Display the content PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => auf_Import + !! Import from HDF5File PROCEDURE, PUBLIC, PASS(obj) :: Export => auf_Export + !! Export to HDF5File PROCEDURE, PASS(obj) :: ImportFromToml1 => auf_ImportFromToml1 + !! Import from toml PROCEDURE, PASS(obj) :: ImportFromToml2 => auf_ImportFromToml2 + !! Import from toml GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & & ImportFromToml2 !! Import abstract kernel from toml PROCEDURE, PUBLIC, PASS(obj) :: ImportParamFromToml => & & auf_ImportParamFromToml + !! Import param from toml END TYPE UserFunction_ !---------------------------------------------------------------------------- @@ -185,9 +208,12 @@ END SUBROUTINE auf_CheckEssentialParam ! summary: Sets user funciton parameter INTERFACE - MODULE SUBROUTINE SetUserFunctionParam(param, returnType, argType, & + MODULE SUBROUTINE SetUserFunctionParam(param, name, returnType, argType, & & numArgs, numReturns, luaScript, luaFunctionName, returnShape) TYPE(ParameterList_), INTENT(INOUT) :: param + !! parameter to be constructed + CHARACTER(*), INTENT(IN) :: name + !! name of the function INTEGER(I4B), INTENT(IN) :: returnType !! Scalar, Vector, Matrix INTEGER(I4B), INTENT(IN) :: argType @@ -327,6 +353,21 @@ MODULE PURE FUNCTION auf_GetReturnType(obj) RESULT(ans) END FUNCTION auf_GetReturnType END INTERFACE +!---------------------------------------------------------------------------- +! GetName@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-23 +! summary: Get name of the function + +INTERFACE + MODULE PURE FUNCTION auf_GetName(obj) RESULT(ans) + CLASS(UserFunction_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION auf_GetName +END INTERFACE + !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/Toml/src/include/ReadMatrix.inc b/src/submodules/Toml/src/include/ReadMatrix.inc index 4549ea737..447835199 100644 --- a/src/submodules/Toml/src/include/ReadMatrix.inc +++ b/src/submodules/Toml/src/include/ReadMatrix.inc @@ -23,12 +23,18 @@ LOGICAL(LGT) :: isFound0, bool1 isFound0 = .FALSE. + stat0 = -1 + + IF (PRESENT(isFound)) isFound = isFound0 + IF (PRESENT(stat)) stat = stat0 + ! try to read from the array array => NULL() - CALL toml_get(table, key, array, & - & origin=origin, stat=stat, requested=.FALSE.) + CALL toml_get(table, key, array, origin=origin, stat=stat0, & + & requested=.FALSE.) IF (ASSOCIATED(array)) THEN + trow = toml_len(array) DO ii = 1, trow row_array => NULL() @@ -56,13 +62,14 @@ CALL toml_get(row_array, jj, VALUE(ii, jj)) END DO END DO + + IF (PRESENT(isFound)) isFound = isFound0 + IF (PRESENT(stat)) stat = stat0 END IF ! try to read from the file CALL toml_get(table, key, filename%raw, origin=origin, stat=stat0) - IF (PRESENT(stat)) stat = stat0 - IF (stat0 .EQ. toml_stat%success) THEN CALL atxtfile%Initiate(filename=filename%Chars(), & & action="READ", status="OLD") @@ -78,9 +85,10 @@ END IF isFound0 = .TRUE. CALL atxtfile%DEALLOCATE() - END IF - IF (PRESENT(isFound)) isFound = isFound0 + IF (PRESENT(stat)) stat = stat0 + IF (PRESENT(isFound)) isFound = isFound0 + END IF filename = "" NULLIFY (array) diff --git a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 index 68f03466d..ad66c0fa8 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 @@ -72,6 +72,8 @@ & VALUE=returnType) CALL Set(obj=param, dataType=1_I4B, prefix=myprefix, key="argType", & & VALUE=argType) +CALL Set(obj=param, dataType="char", prefix=myprefix, key="name", & + & VALUE=name) IF (PRESENT(numArgs)) THEN numArgs0 = numArgs @@ -214,7 +216,7 @@ TYPE(String) :: astr astr = "/isLuaScript/luaScript/numReturns/numArgs/returnType/argType"// & - &"/luaFunctionName/returnShape" + &"/luaFunctionName/returnShape/name" CALL astr%Split(essentialParam, sep="/") CALL CheckEssentialParam(obj=param, & @@ -250,6 +252,7 @@ obj%numArgs = 0 obj%numReturns = 0 obj%scalarValue = 0.0_DFP +obj%name = "" IF (ALLOCATED(obj%vectorValue)) DEALLOCATE (obj%vectorValue) IF (ALLOCATED(obj%matrixValue)) DEALLOCATE (obj%matrixValue) IF (ASSOCIATED(obj%scalarFunction)) obj%scalarFunction => NULL() @@ -273,6 +276,9 @@ CALL obj%DEALLOCATE() CALL obj%CheckEssentialParam(param) +CALL GetValue(obj=param, prefix=myprefix, key="name", & + & VALUE=obj%name) + CALL GetValue(obj=param, prefix=myprefix, key="returnType", & & VALUE=obj%returnType) diff --git a/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 index 4ee12dfa8..b2349cd8a 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@GetMethods.F90 @@ -20,6 +20,14 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! GetName +!---------------------------------------------------------------------------- + +MODULE PROCEDURE auf_GetName +ans = obj%name%chars() +END PROCEDURE auf_GetName + !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- diff --git a/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 index 7862b3ca3..b82825ab7 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 @@ -39,6 +39,7 @@ RETURN END IF +CALL Display("name: "//obj%name, unitNo=unitNo) CALL Display(obj%isUserFunctionSet, "isUserFunctionSet: ", unitNo=unitNo) CALL Display(obj%isLuaScript, "isLuaScript: ", unitNo=unitNo) IF (obj%isLuaScript) THEN @@ -49,7 +50,7 @@ CALL Display(NAME_RETURN_TYPE(obj%returnType), "returnType: ", & & unitNo=unitNo) IF (obj%returnType .EQ. Matrix) THEN - CALL Display(obj%returnShape, "Shape of returnType: ", unitNo=unitNo) + CALL Display(obj%returnShape, "shape of returnType: ", unitNo=unitNo) END IF CALL Display(NAME_ARG_TYPE(obj%argType), "argType: ", & @@ -95,20 +96,31 @@ MODULE PROCEDURE auf_Import CHARACTER(*), PARAMETER :: myName = "auf_Import" TYPE(String) :: dsetname, strval -!> main -!> info -CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Importing the instance of UserFunction_ data") -!> check + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//"::"//myName//" - "// & + & "[START] Import()") +#endif + IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file is not opened') END IF -!> check + IF (.NOT. hdf5%isRead()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have read permission') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file does not have read permission') +END IF + +!> name +dsetname = TRIM(group)//"/name" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%name) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: name should be present.') END IF + !> isUserFunctionSet dsetname = TRIM(group)//"/isUserFunctionSet" IF (hdf5%pathExists(dsetname%chars())) THEN @@ -116,6 +128,7 @@ ELSE obj%isUserFunctionSet = .FALSE. END IF + !> isUserFunctionSet IF (obj%isUserFunctionSet) THEN ! dsetname = TRIM(group)//"/userFunction" @@ -123,25 +136,29 @@ ! CALL obj%userFunction%IMPORT(hdf5=hdf5, group=dsetname%chars()) CALL e%RaiseError(modName//'::'//myName//' - '// & & '[WIP ERROR] :: currently import does not work for useFunction') -ELSE +END IF + +IF (.NOT. obj%isUserFunctionSet) THEN !> returnType dsetname = TRIM(group)//"/returnType" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'dsetname '//dsetname%chars()//'is not present in HDFFile_') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) obj%returnType = UserFunctionGetReturnType(strval%chars()) END IF + !> argType dsetname = TRIM(group)//"/argType" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'dsetname '//dsetname%chars()//'is not present in HDFFile_') ELSE CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) obj%argType = UserFunctionGetArgType(strval%chars()) END IF + !> check the argType, and decide the importer IF (obj%argType .EQ. CONSTANT) THEN !> scalarValue, vectorValue, matrixValue @@ -166,10 +183,15 @@ END IF END SELECT ELSE - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Currently, EASIFEM Supports import of constant userFunction.') END IF END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif END PROCEDURE auf_Import !---------------------------------------------------------------------------- @@ -180,22 +202,27 @@ CHARACTER(*), PARAMETER :: myName = "auf_Export" TYPE(String) :: dsetname, strval -!> info -CALL e%raiseInformation(modName//"::"//myName//" - "// & - & "Exporting the instance of UserFunction_ data") +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif !> check IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file is not opened') END IF !> check IF (.NOT. hdf5%isWrite()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have write permission') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file does not have write permission') END IF +!> name +dsetname = TRIM(group)//"/name" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%name) + !> isUserFunctionSet IF (obj%isUserFunctionSet) THEN !> isUserFunctionSet @@ -207,14 +234,18 @@ CALL e%RaiseError(modName//'::'//myName//' - '// & & '[WIP ERROR] :: Currently export function does not work '// & & ' for UserFunction.') -ELSE +END IF + +IF (.NOT. obj%isUserFunctionSet) THEN !> isUserFunctionSet dsetname = TRIM(group)//"/isUserFunctionSet" CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isUserFunctionSet) + !> returnType dsetname = TRIM(group)//"/returnType" strval = NAME_RETURN_TYPE(obj%returnType) CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) + !> argType dsetname = TRIM(group)//"/argType" strval = NAME_ARG_TYPE(obj%argType) @@ -238,10 +269,15 @@ & CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%matrixValue) END SELECT ELSE - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'Currently, EASIFEM Supports import of constant userFunction.') END IF END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif END PROCEDURE auf_Export !---------------------------------------------------------------------------- @@ -253,7 +289,7 @@ INTEGER(I4B) :: origin, stat LOGICAL(LGT) :: bool1, isLuaScript, isFound INTEGER(I4B) :: argType, returnType, numReturns, numArgs -TYPE(String) :: astr, luaScript, luaFunctionName +TYPE(String) :: astr, luaScript, luaFunctionName, name INTEGER(I4B), ALLOCATABLE :: returnShape(:) #ifdef DEBUG_VER @@ -271,6 +307,17 @@ END IF returnType = UserFunctionGetReturnType(astr%chars()) +astr = "" +CALL toml_get(table, "name", astr%raw, origin=origin, stat=stat) +bool1 = stat .NE. toml_stat%success +IF (bool1) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: name should be present, and '// & + & 'it is a string.') + RETURN +END IF +name = astr%chars() + CALL Reallocate(returnShape, 2) returnShape = [0, 0] IF (returnType .EQ. Matrix) THEN @@ -330,7 +377,8 @@ END IF IF (isLuaScript) THEN - CALL SetUserFunctionParam(param=param, & + CALL SetUserFunctionParam(param=param, & + & name=name%chars(), & & returnType=returnType, & & returnShape=returnShape, & & argType=argType, & @@ -339,7 +387,8 @@ & luaScript=luaScript%chars(), & & luaFunctionName=luaFunctionName%chars()) ELSE - CALL SetUserFunctionParam(param=param, & + CALL SetUserFunctionParam(param=param, & + & name=name%chars(), & & returnType=returnType, & & returnShape=returnShape, & & argType=argType, & @@ -387,6 +436,7 @@ RETURN END IF CALL obj%Set(scalarValue=scalarValue) + CASE (Vector) CALL GetValue(table=table, key="vectorValue", & & VALUE=vectorValue, origin=origin, stat=stat, isFound=isFound) diff --git a/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 index 3d3ddd18d..34d20f860 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@SetMethods.F90 @@ -15,13 +15,13 @@ ! along with this program. If not, see ! -SUBMODULE(UserFunction_Class) SetMethods -USE BaseMethod -IMPLICIT NONE -CONTAINS - -!---------------------------------------------------------------------------- +! SUBMODULE(UserFunction_Class) SetMethods +! USE BaseMethod +! IMPLICIT NONE +! CONTAINS ! -!---------------------------------------------------------------------------- - -END SUBMODULE SetMethods +! !---------------------------------------------------------------------------- +! ! +! !---------------------------------------------------------------------------- +! +! END SUBMODULE SetMethods From b3cb0301b49b80104c6e839ffa7e72fc6baf65d7 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 23:02:15 +0900 Subject: [PATCH 019/117] Improving Toml support in UserFunction_ - Removing a bug caused due to the duplicate of GetName function in constructor and get methods submodules. --- .../src/UserFunction_Class@ConstructorMethods.F90 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 index 1adf03e64..ad66c0fa8 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 @@ -21,14 +21,6 @@ IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! GetName -!---------------------------------------------------------------------------- - -MODULE PROCEDURE auf_GetName - ans = obj%name%chars() -END PROCEDURE auf_GetName - !---------------------------------------------------------------------------- ! UserFunctionGetReturnType !---------------------------------------------------------------------------- From c48b051812a733a5ac4c6de9cfeed4a0a921a53e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 23:03:25 +0900 Subject: [PATCH 020/117] Improving cmake for Gmsh Enhancing the capability of locating gmsh sdk on systems. --- cmake/Modules/FindGmsh.cmake | 40 +++++++++++++++ cmake/addGmsh-old.cmake | 35 -------------- cmake/addGmsh.cmake | 94 ++++++++++++++++++------------------ 3 files changed, 88 insertions(+), 81 deletions(-) create mode 100644 cmake/Modules/FindGmsh.cmake delete mode 100644 cmake/addGmsh-old.cmake diff --git a/cmake/Modules/FindGmsh.cmake b/cmake/Modules/FindGmsh.cmake new file mode 100644 index 000000000..a8218dad0 --- /dev/null +++ b/cmake/Modules/FindGmsh.cmake @@ -0,0 +1,40 @@ +# ############################################################################## +# Try to find Gmsh # # Once done this +# will define: # GMSH_FOUND - system has Gmsh # +# GMSH_INC - Gmsh include directory (static or dynamic) # GMSH_LIB - +# Gmsh library # # Usage: # find_package(Gmsh) # # +# Setting these changes the behavior of the search # GMSH_INC - Gmsh +# include directory # GMSH_LIB - Gmsh library path +# (static or dynamic) # +# ############################################################################## + +# Try to set GMSH_LIB and GMSH_INC from environment variables ## +# ############################################################################## + +if(NOT DEFINED GMSH_LIB) + + find_package(Python3 COMPONENTS Interpreter Development) + + if(Python3_FOUND) + message(STATUS "FOUND Python3") + message(STATUS "Python3_LIBRARY_DIRS ${Python3_LIBRARY_DIRS}") + find_library(GMSH_LIB "gmsh" HINTS $ENV{GMSH_LIB} ${Python3_LIBRARY_DIRS} + NO_CACHE) + else() + message(STATUS "NOT FOUND Python3") + find_library(GMSH_LIB "gmsh" HINTS $ENV{GMSH_LIB} NO_CACHE) + endif() +endif() + +if(NOT DEFINED GMSH_INC) + find_path(GMSH_INC "gmsh.h" HINTS $ENV{GMSH_INC} NO_CACHE) +endif() + +# CMake check and done ## +# ############################################################################## +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Gmsh + "Gmsh could not be found: be sure to set GMSH_LIB and GMSH_INC in your environment variables" + GMSH_LIB + GMSH_INC) diff --git a/cmake/addGmsh-old.cmake b/cmake/addGmsh-old.cmake deleted file mode 100644 index 897195819..000000000 --- a/cmake/addGmsh-old.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# 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 -# -#GMSH SDK -IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) - OPTION( USE_GMSH_SDK OFF ) - IF( USE_GMSH_SDK ) - LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) - IF( UNIX ) - IF(APPLE) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.dylib" ) - ELSE() - # SET( GMSH_LIBRARIES "$ENV{HOME}/.local/lib/libgmsh.so" ) - SET( GMSH_LIBRARIES "$ENV{EASIFEM_EXTPKGS}/lib/libgmsh.so" ) - ENDIF() - ENDIF() - TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) - MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) - ELSE() - MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) - ENDIF() -ENDIF() diff --git a/cmake/addGmsh.cmake b/cmake/addGmsh.cmake index 39cecb6e8..ce8ef6755 100644 --- a/cmake/addGmsh.cmake +++ b/cmake/addGmsh.cmake @@ -1,47 +1,49 @@ -# 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 -# -#GMSH SDK -IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) - OPTION( USE_GMSH_SDK OFF ) - IF( USE_GMSH_SDK ) - LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) - FIND_PACKAGE(PkgConfig REQUIRED) - FIND_LIBRARY(GMSH_LIBRARY - NAMES gmsh gmsh.4.12 - PATHS "$ENV{CONDA_PREFIX}/lib" "/opt/homebrew/lib" ) - # PATHS "/opt/homebrew/lib" ) - SET(GMSH_LIBRARIES ${GMSH_LIBRARY}) - - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS( - GMSH DEFAULT_MSG - GMSH_LIBRARIES - ) - - # SET(GMSH_LIBRARIES "$ENV{CONDA_PREFIX}/lib/libgmsh.so") - - TARGET_LINK_LIBRARIES( - ${PROJECT_NAME} - PUBLIC - ${GMSH_LIBRARIES} - ) +# 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 +# +# GMSH SDK IF( ${PROJECT_NAME} MATCHES "easifemClasses" ) OPTION( USE_GMSH_SDK +# OFF ) IF( USE_GMSH_SDK ) LIST( APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK" ) +# FIND_PACKAGE(PkgConfig REQUIRED) FIND_LIBRARY(GMSH_LIBRARY NAMES gmsh PATHS +# "$ENV{CONDA_PREFIX}/lib" "/opt/homebrew/lib" ) # PATHS "/opt/homebrew/lib" ) +# SET(GMSH_LIBRARIES ${GMSH_LIBRARY}) +# +# INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS( GMSH +# DEFAULT_MSG GMSH_LIBRARIES ) +# +# # SET(GMSH_LIBRARIES "$ENV{CONDA_PREFIX}/lib/libgmsh.so") +# +# TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC ${GMSH_LIBRARIES} ) +# +# MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) ELSE() MESSAGE( STATUS +# "NOT USING GMSH SDK LIBRARIES" ) ENDIF() ENDIF() - MESSAGE( STATUS "GMSH_LIBRARIES : ${GMSH_LIBRARIES}" ) - ELSE() - MESSAGE( STATUS "NOT USING GMSH SDK LIBRARIES" ) - ENDIF() -ENDIF() +if(${PROJECT_NAME} MATCHES "easifemClasses") + option(USE_GMSH_SDK OFF) + if(USE_GMSH_SDK) + message(STATUS "USING GMSH SDK") + list(APPEND TARGET_COMPILE_DEF "-DUSE_GMSH_SDK") + find_package(Gmsh REQUIRED) + if(GMSH_FOUND) + message(STATUS "FOUND Gmsh") + message(STATUS "GMSH_LIBRARIES : ${GMSH_LIB}") + target_link_libraries(${PROJECT_NAME} PUBLIC ${GMSH_LIB}) + else() + message(STATUS "NOT FOUND Gmsh") + endif() + else() + message(STATUS "NOT USING GMSH SDK") + endif() +endif() From 3862b11e67e1e735b906cc0ccf008ffc1979e690 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 23 Nov 2023 23:41:45 +0900 Subject: [PATCH 021/117] Fixing ftlPointerVector Fixes #185 --- src/modules/ftlMacros/ftlPointerVector.inc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/modules/ftlMacros/ftlPointerVector.inc b/src/modules/ftlMacros/ftlPointerVector.inc index 466a5ae4c..11cfca16a 100644 --- a/src/modules/ftlMacros/ftlPointerVector.inc +++ b/src/modules/ftlMacros/ftlPointerVector.inc @@ -610,7 +610,8 @@ SUBROUTINE T_SetSingleAtIndex(obj, pos, val) & "While setting the value pos is greater than the length of list") ELSE IF( ASSOCIATED( obj%storage(pos)%ptr ) ) THEN - DEALLOCATE( obj%storage(pos)%ptr ) + CALL obj%storage(pos)%ptr%Deallocate() + NULLIFY(obj%storage(pos)%ptr) END IF obj%storage(pos)%ptr => val%ptr END IF @@ -653,7 +654,8 @@ SUBROUTINE T_SetFillAtIndex(obj, pos, n, val) & "While setting the value pos0 is greater than the length of list") ELSE IF( ASSOCIATED( obj%storage(pos0)%ptr ) ) THEN - DEALLOCATE( obj%storage(pos0)%ptr ) + CALL obj%storage(pos0)%ptr%Deallocate() + obj%storage(pos0)%ptr => NULL() END IF obj%storage(pos0)%ptr => val%ptr END IF @@ -695,7 +697,8 @@ SUBROUTINE T_SetArrayAtIndex( obj, pos, array ) & "While setting the value pos0 is greater than the length of list") ELSE IF( ASSOCIATED( obj%storage(pos0)%ptr ) ) THEN - DEALLOCATE( obj%storage(pos0)%ptr ) + CALL obj%storage(pos0)%ptr%Deallocate() + obj%storage(pos0)%ptr => NULL() END IF obj%storage(pos0)%ptr => array(ii)%ptr END IF @@ -929,7 +932,7 @@ SUBROUTINE TriggerFinalizer(obj, freeMem) LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: freeMem IF( PRESENT(freeMem) )THEN IF( freeMem ) THEN - DEALLOCATE(obj%ptr) + CALL obj%ptr%Deallocate() NULLIFY(obj%ptr) ELSE NULLIFY(obj%ptr) @@ -1227,4 +1230,4 @@ END MODULE ! #define FTL_TEMPLATE_TYPE_NAME Element ! #define FTL_TEMPLATE_TYPE_IS_DERIVED ! #define FTL_TEMPLATE_TYPE ElementPointer_ -! #define USE FTL_TEMPLATE_TYPE_MODULE ElementFactory \ No newline at end of file +! #define USE FTL_TEMPLATE_TYPE_MODULE ElementFactory From dc1c01ebec9c225bfde70ab7058a3cdb3ce93e92 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Fri, 24 Nov 2023 00:30:28 +0900 Subject: [PATCH 022/117] Updates in AbstractNodeField_Class - Restructuring the module - Minor formatting --- .../AbstractField/src/AbstractField_Class.F90 | 4 + .../src/AbstractNodeField_Class.F90 | 82 +++++++---- .../AbstractNodeField/CMakeLists.txt | 29 +++- ...ractNodeField_Class@ConstructorMethods.F90 | 139 ++++++++++++++++++ .../AbstractNodeField_Class@GetMethods.F90 | 80 ++++++++++ .../src/AbstractNodeField_Class@IOMethods.F90 | 114 ++++++++++++++ .../src/AbstractNodeField_Class@Methods.F90 | 1 - .../AbstractNodeField_Class@SetMethods.F90 | 84 +++++++++++ 8 files changed, 498 insertions(+), 35 deletions(-) create mode 100644 src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 create mode 100644 src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 create mode 100644 src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 create mode 100644 src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index f3c45f064..1e345e62a 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -413,6 +413,10 @@ END SUBROUTINE aField_WriteData_hdf5 ! !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-24 +! summary: Export data in vrkfile + INTERFACE MODULE SUBROUTINE aField_WriteData_vtk(obj, vtk, group) CLASS(AbstractField_), INTENT(INOUT) :: obj diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index e26a96860..9526d5902 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -22,6 +22,7 @@ MODULE AbstractNodeField_Class USE Domain_Class, ONLY: DomainPointer_, Domain_ USE HDF5File_Class, ONLY: HDF5File_ USE VTKFile_Class, ONLY: VTKFile_ +USE ExceptionHandler_Class, ONLY: e IMPLICIT NONE PRIVATE PUBLIC :: AbstractNodeFieldDisplay @@ -77,29 +78,44 @@ MODULE AbstractNodeField_Class !! how the different components are stored inside the realVec !! NOTE: This variable is only for internal use CONTAINS + PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => anf_Initiate2 + !! Initiate an instance of AbstrtactNodeField + PROCEDURE, PUBLIC, PASS(obj) :: Initiate3 => anf_Initiate3 + !! Initiate an instance of AbstrtactNodeField + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => anf_Deallocate + !! Deallocate the data stored inside + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => anf_Display !! Display the content of AbstractNodeField PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => anf_Import !! Import AbstractNodeField from HDF5File_ PROCEDURE, PUBLIC, PASS(obj) :: Export => anf_Export !! Export AbstractNodeField to HDF5File_ + ! PROCEDURE, PUBLIC, PASS(obj) :: WriteData_vtk => anf_WriteData_vtk + !! Export data in VTKformat + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetPointer => anf_GetPointer !! GetPointer to the fortran vector stored inside the realvec !! This function should be called for Native engine only PROCEDURE, PUBLIC, PASS(obj) :: Size => anf_Size !! Returns the length of data stored inside the fortran vector - PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => anf_Initiate2 - !! Initiate an instance of AbstrtactNodeField - PROCEDURE, PUBLIC, PASS(obj) :: Initiate3 => anf_Initiate3 - !! Initiate an instance of AbstrtactNodeField - PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => anf_Deallocate - !! Deallocate the data stored inside PROCEDURE, PUBLIC, PASS(obj) :: Norm2 => anf_Norm2 !! Returns the L2 norm - PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => anf_SetSingle - !! Set single entry PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => anf_GetSingle !! Get single entry + + ! SET: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => anf_SetSingle + !! Set single entry END TYPE AbstractNodeField_ !---------------------------------------------------------------------------- @@ -154,23 +170,23 @@ END SUBROUTINE AbstractNodeFieldInitiate ! Display !---------------------------------------------------------------------------- -INTERFACE +INTERFACE AbstractNodeFieldDisplay MODULE SUBROUTINE anf_Display(obj, msg, unitNo) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo END SUBROUTINE anf_Display -END INTERFACE - -INTERFACE AbstractNodeFieldDisplay - MODULE PROCEDURE anf_Display END INTERFACE AbstractNodeFieldDisplay !---------------------------------------------------------------------------- ! IMPORT !---------------------------------------------------------------------------- -INTERFACE +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-24 +! summary: Import data into HDF5File_ + +INTERFACE AbstractNodeFieldImport MODULE SUBROUTINE anf_Import(obj, hdf5, group, dom, domains) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 @@ -178,28 +194,40 @@ MODULE SUBROUTINE anf_Import(obj, hdf5, group, dom, domains) TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE anf_Import -END INTERFACE - -INTERFACE AbstractNodeFieldImport - MODULE PROCEDURE anf_Import END INTERFACE AbstractNodeFieldImport !---------------------------------------------------------------------------- -! Export +! Export@IOMethods !---------------------------------------------------------------------------- -INTERFACE +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-24 +! summary: Export data into HDF5File_ + +INTERFACE AbstractNodeFieldExport MODULE SUBROUTINE anf_Export(obj, hdf5, group) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE anf_Export -END INTERFACE - -INTERFACE AbstractNodeFieldExport - MODULE PROCEDURE anf_Export END INTERFACE AbstractNodeFieldExport +!---------------------------------------------------------------------------- +! WriteData@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-24 +! summary: Export data in vrkfile + +! INTERFACE AbstractNodeWriteData +! MODULE SUBROUTINE anf_WriteData_vtk(obj, vtk, group) +! CLASS(AbstractNodeField_), INTENT(INOUT) :: obj +! TYPE(VTKFile_), INTENT(INOUT) :: vtk +! CHARACTER(*), INTENT(IN) :: group +! END SUBROUTINE anf_WriteData_vtk +! END INTERFACE AbstractNodeWriteData + !---------------------------------------------------------------------------- ! GetPointer !---------------------------------------------------------------------------- @@ -208,15 +236,11 @@ END SUBROUTINE anf_Export ! date: 20 Jul 2021 ! summary: Returns the pointer to a fortran real vector stored inside realVec -INTERFACE +INTERFACE AbstractNodeFieldGetPointer MODULE FUNCTION anf_GetPointer(obj) RESULT(ans) CLASS(AbstractNodeField_), TARGET, INTENT(IN) :: obj REAL(DFP), POINTER :: ans(:) END FUNCTION anf_GetPointer -END INTERFACE - -INTERFACE AbstractNodeFieldGetPointer - MODULE PROCEDURE anf_GetPointer END INTERFACE AbstractNodeFieldGetPointer !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/CMakeLists.txt b/src/submodules/AbstractNodeField/CMakeLists.txt index 7e284bb2d..87c094793 100644 --- a/src/submodules/AbstractNodeField/CMakeLists.txt +++ b/src/submodules/AbstractNodeField/CMakeLists.txt @@ -1,5 +1,24 @@ -SET(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") -TARGET_SOURCES( - ${PROJECT_NAME} PRIVATE - ${src_path}/AbstractNodeField_Class@Methods.F90 -) \ No newline at end of file +# 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}/AbstractNodeField_Class@ConstructorMethods.F90 + ${src_path}/AbstractNodeField_Class@GetMethods.F90 + ${src_path}/AbstractNodeField_Class@SetMethods.F90 + ${src_path}/AbstractNodeField_Class@IOMethods.F90) diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..37877edfb --- /dev/null +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 @@ -0,0 +1,139 @@ +! 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(AbstractNodeField_Class) ConstructorMethods +USE BaseMethod +USE HDF5File_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Initiate2 +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Initiate2 +CHARACTER(*), PARAMETER :: myName = "anf_Initiate2" +INTEGER(I4B) :: ii, tsize + +CALL obj%DEALLOCATE() +CALL AbstractFieldInitiate2( & + & obj=obj, & + & obj2=obj2, & + & copyFull=copyFull, & + & copyStructure=copyStructure, & + & usePointer=usePointer) + +SELECT TYPE (obj2); CLASS IS (AbstractNodeField_) + obj%tSize = obj2%tSize + obj%realVec = obj2%realVec + obj%dof = obj2%dof +END SELECT + +END PROCEDURE anf_Initiate2 + +!---------------------------------------------------------------------------- +! anf_Initiate3 +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Initiate3 +CHARACTER(*), PARAMETER :: myName = "anf_Initiate3" +CALL e%raiseError(modName//'::'//myName//" - "// & + & '[IMPLEMENTATION ERROR] :: Initiate3 should be implemented by the'// & + & ' child of AbstractNodeField_') +END PROCEDURE anf_Initiate3 + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Deallocate +CALL AbstractFieldDeallocate(obj) +obj%tSize = 0 +CALL DEALLOCATE (obj%realVec) +CALL DEALLOCATE (obj%dof) +obj%dof_tPhysicalVars = 0 +obj%dof_storageFMT = NODES_FMT +IF (ALLOCATED(obj%dof_spaceCompo)) DEALLOCATE (obj%dof_spaceCompo) +IF (ALLOCATED(obj%dof_timeCompo)) DEALLOCATE (obj%dof_timeCompo) +IF (ALLOCATED(obj%dof_tNodes)) DEALLOCATE (obj%dof_tNodes) +IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) +END PROCEDURE anf_Deallocate + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractNodeFieldInitiate +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate" + +CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) + +IF (obj%dof_tPhysicalVars .EQ. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_tPhysicalVars is 0') +END IF + +IF (.NOT. ALLOCATED(obj%dof_spaceCompo)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_spaceCompo '// & + & ' is NOT ALLOCATED') +END IF + +IF (.NOT. ALLOCATED(obj%dof_timeCompo)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_timeCompo '// & + & ' is NOT ALLOCATED') +END IF + +IF (.NOT. ALLOCATED(obj%dof_tNodes)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_tNodes '// & + & ' is NOT ALLOCATED') +END IF + +IF (.NOT. ALLOCATED(obj%dof_names_char)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_names_char '// & + & ' is NOT ALLOCATED') +END IF + +CALL Initiate( & + & obj=obj%dof, & + & tNodes=obj%dof_tNodes, & + & names=obj%dof_names_char, & + & spaceCompo=obj%dof_spaceCompo, & + & timeCompo=obj%dof_timeCompo, & + & storageFMT=obj%dof_storageFMT) + +CALL Initiate(obj=obj%realVec, dofobj=obj%dof) + +obj%tSize = SIZE(obj%realVec) + +IF (obj%local_n .EQ. 0) THEN + obj%local_n = obj%tSize +END IF + +IF (obj%global_n .EQ. 0) THEN + obj%global_n = obj%tSize +END IF + +END PROCEDURE AbstractNodeFieldInitiate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 new file mode 100644 index 000000000..be4bd8afa --- /dev/null +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 @@ -0,0 +1,80 @@ +! 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(AbstractNodeField_Class) GetMethods +USE BaseMethod +USE HDF5File_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! GetPointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetPointer +ans => GetPointer(obj%realVec) +END PROCEDURE anf_GetPointer + +!---------------------------------------------------------------------------- +! Size +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_size +CHARACTER(*), PARAMETER :: myName = "anf_size" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') +! ans = obj%tSize +END PROCEDURE anf_size + +!---------------------------------------------------------------------------- +! Norm2 +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Norm2 +CHARACTER(*), PARAMETER :: myName = "anf_Norm2" +IF (obj%engine%chars() .EQ. "NATIVE_SERIAL") THEN + ans = NORM2(obj=obj%realvec) +ELSE + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'This method has been implemented for NATIVE engines') + ans = 0.0_DFP +END IF +END PROCEDURE anf_Norm2 + +!---------------------------------------------------------------------------- +! GetSingle +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetSingle +IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN + VALUE = Get( & + & obj=obj%realVec, & + & nodenum=1, & + & dataType=1.0_DFP) +ELSE + VALUE = Get( & + & obj=obj%realVec, & + & nodenum=indx, & + & dataType=1.0_DFP) +END IF +END PROCEDURE anf_GetSingle + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE GetMethods diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 new file mode 100644 index 000000000..682a6bb48 --- /dev/null +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 @@ -0,0 +1,114 @@ +! 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(AbstractNodeField_Class) IOMethods +USE BaseMethod +USE HDF5File_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Display +CALL AbstractFieldDisplay(obj=obj, msg=msg, unitNo=unitNo) +CALL Display(obj%tSize, "# tSize : ", unitNo=unitNo) +CALL Display(obj%realVec, obj%dof, "# realVec : ", unitNo=unitNo) +END PROCEDURE anf_Display + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Import +CHARACTER(*), PARAMETER :: myName = "anf_Import" +TYPE(String) :: dsetname +LOGICAL(LGT) :: abool +TYPE(ParameterList_) :: param + +CALL e%raiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') + +CALL AbstractFieldImport( & + & obj=obj, & + & hdf5=hdf5, & + & group=group, & + & dom=dom, & + & domains=domains) + +dsetname = TRIM(group)//"/tSize" +abool = hdf5%pathExists(dsetname%chars()) +IF (abool) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%tSize) +END IF + +dsetname = TRIM(group)//"/dof" +abool = hdf5%pathExists(dsetname%chars()) +IF (abool) THEN + CALL ImportDOF(obj=obj%dof, hdf5=hdf5, group=dsetname%chars()) +END IF + +dsetname = TRIM(group)//"/realVec" +abool = hdf5%pathExists(dsetname%chars()) +IF (abool) THEN + CALL ImportRealVector(obj=obj%realvec, hdf5=hdf5, & + & group=dsetname%chars()) +END IF + +! info +CALL e%raiseInformation(modName//"::"//myName//" - "// & + & "[END] Import()") + +END PROCEDURE anf_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Export +CHARACTER(*), PARAMETER :: myName = "anf_Export" +TYPE(String) :: strval, dsetname + +CALL e%raiseInformation(modName//"::"//myName//" - "// & + & "[START] Export()") + +CALL AbstractFieldExport(obj=obj, hdf5=hdf5, group=group) + +! tSize +dsetname = TRIM(group)//"/tSize" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%tSize) + +! dof +dsetname = TRIM(group)//"/dof" +CALL ExportDOF(obj=obj%dof, hdf5=hdf5, group=dsetname%chars()) + +! realVec +dsetname = TRIM(group)//"/realVec" +CALL ExportRealVector(obj=obj%realVec, hdf5=hdf5, & + & group=dsetname%chars()) + +! info +CALL e%raiseInformation(modName//"::"//myName//" - "// & + & "[END] Export()") + +END PROCEDURE anf_Export + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE IOMethods diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 index a773171db..98a0f5f71 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@Methods.F90 @@ -16,7 +16,6 @@ SUBMODULE(AbstractNodeField_Class) Methods USE BaseMethod -USE ExceptionHandler_Class, ONLY: e USE HDF5File_Method IMPLICIT NONE CONTAINS diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 new file mode 100644 index 000000000..2e73420a0 --- /dev/null +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 @@ -0,0 +1,84 @@ +! 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(AbstractNodeField_Class) SetMethods +USE BaseMethod +USE HDF5File_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_SetParam +INTEGER(I4B) :: ii + +IF (PRESENT(dof_tPhysicalVars)) THEN + obj%dof_tPhysicalVars = dof_tPhysicalVars +END IF + +IF (PRESENT(dof_storageFMT)) THEN + obj%dof_storageFMT = dof_storageFMT +END IF + +IF (PRESENT(dof_spaceCompo)) THEN + obj%dof_spaceCompo = dof_spaceCompo +END IF + +IF (PRESENT(dof_timeCompo)) THEN + obj%dof_timeCompo = dof_timeCompo +END IF + +IF (PRESENT(dof_tNodes)) THEN + obj%dof_tNodes = dof_tNodes +END IF + +IF (PRESENT(dof_names_char)) THEN + IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) + ALLOCATE (obj%dof_names_char(SIZE(dof_names_char))) + DO ii = 1, SIZE(dof_names_char) + obj%dof_names_char(ii) = obj%dof_names_char(ii) + END DO +END IF + +END PROCEDURE anf_SetParam + +!---------------------------------------------------------------------------- +! SetSingle +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_SetSingle +IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN + IF (PRESENT(addContribution)) THEN + CALL add(obj%realVec, nodenum=1, VALUE=VALUE, scale=scale) + ELSE + CALL set(obj%realVec, nodenum=1, VALUE=VALUE) + END IF +ELSE + IF (PRESENT(addContribution)) THEN + CALL add(obj%realVec, nodenum=indx, VALUE=VALUE, scale=scale) + ELSE + CALL set(obj%realVec, nodenum=indx, VALUE=VALUE) + END IF +END IF +END PROCEDURE anf_SetSingle + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE SetMethods From 668ab3b16b73c9aeb017bdad507d8dc45245717d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Fri, 24 Nov 2023 17:04:01 +0900 Subject: [PATCH 023/117] Fixing issue #194 Fixes issue #194 --- .../STScalarField_Class@ConstructorMethods.F90 | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index a14296b7a..7fdf32918 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -27,6 +27,7 @@ MODULE PROCEDURE SetSTScalarFieldParam TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr CALL SetAbstractFieldParam( & & param=param, & @@ -39,7 +40,17 @@ & global_n=global_n) sublist => NULL() -sublist => param%NewSubList(key=myprefix) +ierr = param%GetSubList(key=myprefix, sublist=sublist) + +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF CALL Set( & & obj=sublist, & @@ -71,7 +82,7 @@ MODULE PROCEDURE stsField_Initiate1 CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1()" TYPE(String) :: astr -INTEGER(I4B) :: nsd, tdof, ierr, timeCompo, tNodes +INTEGER(I4B) :: nsd, tdof, ierr, timeCompo, tNodes TYPE(ParameterList_), POINTER :: sublist ! main @@ -93,7 +104,7 @@ CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", VALUE=timeCompo) -tNodes = dom%GetTotalNodes() +tNodes = dom%GetTotalNodes() tdof = tNodes * timeCompo CALL AbstractNodeFieldSetParam(obj=obj, & From 5483bfbcaeb37c789d8d3b8bd1bdfbb97a2bf597 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Fri, 24 Nov 2023 17:39:37 +0900 Subject: [PATCH 024/117] Fixes FindGmsh and Issue #194 fixes issue #194 --- cmake/Modules/FindGmsh.cmake | 9 ++++----- .../src/STScalarField_Class@ConstructorMethods.F90 | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/Modules/FindGmsh.cmake b/cmake/Modules/FindGmsh.cmake index a8218dad0..9bf55bf38 100644 --- a/cmake/Modules/FindGmsh.cmake +++ b/cmake/Modules/FindGmsh.cmake @@ -26,9 +26,8 @@ if(NOT DEFINED GMSH_LIB) endif() endif() -if(NOT DEFINED GMSH_INC) - find_path(GMSH_INC "gmsh.h" HINTS $ENV{GMSH_INC} NO_CACHE) -endif() +# if(NOT DEFINED GMSH_INC) find_path(GMSH_INC "gmsh.h" HINTS $ENV{GMSH_INC} +# NO_CACHE) endif() # CMake check and done ## # ############################################################################## @@ -36,5 +35,5 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args( Gmsh "Gmsh could not be found: be sure to set GMSH_LIB and GMSH_INC in your environment variables" - GMSH_LIB - GMSH_INC) + GMSH_LIB) +# GMSH_INC) diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index 7fdf32918..5fce90235 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -26,6 +26,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetSTScalarFieldParam +CHARACTER(*), PARAMETER :: myName = "SetSTScalarFieldParam()" TYPE(ParameterList_), POINTER :: sublist INTEGER(I4B) :: ierr From 593974144707668533538dae3190b44d5838f17c Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Fri, 24 Nov 2023 18:29:45 +0900 Subject: [PATCH 025/117] WIP: dc1c01e Updates in AbstractNodeField_Class --- .../src/AbstractNodeField_Class.F90 | 16 ++--- ...ractNodeField_Class@ConstructorMethods.F90 | 6 +- .../src/AbstractNodeField_Class@IOMethods.F90 | 70 +++++++++++++++++++ 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index 9526d5902..35c57514a 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -97,7 +97,7 @@ MODULE AbstractNodeField_Class !! Import AbstractNodeField from HDF5File_ PROCEDURE, PUBLIC, PASS(obj) :: Export => anf_Export !! Export AbstractNodeField to HDF5File_ - ! PROCEDURE, PUBLIC, PASS(obj) :: WriteData_vtk => anf_WriteData_vtk + PROCEDURE, PUBLIC, PASS(obj) :: WriteData_vtk => anf_WriteData_vtk !! Export data in VTKformat ! GET: @@ -220,13 +220,13 @@ END SUBROUTINE anf_Export ! date: 2023-11-24 ! summary: Export data in vrkfile -! INTERFACE AbstractNodeWriteData -! MODULE SUBROUTINE anf_WriteData_vtk(obj, vtk, group) -! CLASS(AbstractNodeField_), INTENT(INOUT) :: obj -! TYPE(VTKFile_), INTENT(INOUT) :: vtk -! CHARACTER(*), INTENT(IN) :: group -! END SUBROUTINE anf_WriteData_vtk -! END INTERFACE AbstractNodeWriteData +INTERFACE AbstractNodeWriteData + MODULE SUBROUTINE anf_WriteData_vtk(obj, vtk, group) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + TYPE(VTKFile_), INTENT(INOUT) :: vtk + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE anf_WriteData_vtk +END INTERFACE AbstractNodeWriteData !---------------------------------------------------------------------------- ! GetPointer diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 index 37877edfb..2c3761e7d 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 @@ -61,15 +61,15 @@ MODULE PROCEDURE anf_Deallocate CALL AbstractFieldDeallocate(obj) -obj%tSize = 0 -CALL DEALLOCATE (obj%realVec) -CALL DEALLOCATE (obj%dof) obj%dof_tPhysicalVars = 0 obj%dof_storageFMT = NODES_FMT IF (ALLOCATED(obj%dof_spaceCompo)) DEALLOCATE (obj%dof_spaceCompo) IF (ALLOCATED(obj%dof_timeCompo)) DEALLOCATE (obj%dof_timeCompo) IF (ALLOCATED(obj%dof_tNodes)) DEALLOCATE (obj%dof_tNodes) IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) +obj%tSize = 0 +CALL DEALLOCATE (obj%realVec) +CALL DEALLOCATE (obj%dof) END PROCEDURE anf_Deallocate !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 index 682a6bb48..79f0d75cc 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 @@ -107,6 +107,76 @@ END PROCEDURE anf_Export +!---------------------------------------------------------------------------- +! WriteData +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_WriteData +CHARACTER(*), PARAMETER :: myName = "anf_WriteData()" +LOGICAL(LGT) :: isOK +TYPE(Domain_), POINTER :: dom +TYPE(Mesh_), POINTER :: meshPtr +INTEGER(I4B) :: imesh, tMesh +INTEGER(I4B), ALLOCATABLE :: nptrs(:) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] WriteData()') +#endif + +isOK = obj%isInitiated +IF (.NOT. isOK) THEN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj is not isInitiated.') + RETURN +END IF + +isOK = vtk%isOpen() +IF (.NOT. isOK) THEN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') + RETURN +END IF + +isOK = vtk%isWrite() +IF (isOK) THEN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: VTKFile_::vtk does not have write access.') + RETURN +END IF + +isOK = ASSOCIATED(obj%domain) .OR. ALLOCATED(obj%domains) +IF (.NOT. isOK) THEN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & + & ' or obj%domains not allocated.') + RETURN +END IF + +dom => obj%domain +tMesh = dom%GetTotalMesh() + +DO imesh = 1, tMesh + + meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) + CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) + CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, openTag=.TRUE., & + & content=.TRUE., closeTag=.FALSE.) + CALL vtk%WriteDataArray(location=String('node'), action=String('open')) + nptrs = meshPtr%GetNptrs() + ! CALL sol%Get(globalNode=nptrs, value=fe) + ! CALL vtk%WriteDataArray(name=String("sol"), x=fe, numberOfComponents=1) + CALL vtk%WriteDataArray(location=String('node'), action=String('close')) + CALL vtk%WritePiece() + +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] WriteData()') +#endif +END PROCEDURE anf_WriteData + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- From 7d475ca205572b1b9634e38f8160194b0f4529b6 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 17:22:18 +0900 Subject: [PATCH 026/117] Minor formatting in AbstractField Minor formatting in AbstractField_Class. - Better code organization - Improvement in documentation --- .../AbstractField/src/AbstractField_Class.F90 | 190 ++++++----- src/submodules/AbstractField/CMakeLists.txt | 36 +- ...AbstractField_Class@ConstructorMethods.F90 | 238 +++++++++++++ .../src/AbstractField_Class@GetMethods.F90 | 196 +++++++++++ .../src/AbstractField_Class@IOMethods.F90 | 319 ++++++++++++++++++ .../src/AbstractField_Class@SetMethods.F90 | 74 ++++ 6 files changed, 940 insertions(+), 113 deletions(-) create mode 100644 src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 create mode 100644 src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 create mode 100644 src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 create mode 100644 src/submodules/AbstractField/src/AbstractField_Class@SetMethods.F90 diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index 1e345e62a..2adf5b6d9 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -55,6 +55,9 @@ MODULE AbstractField_Class PUBLIC :: FIELD_TYPE_NUMBER PUBLIC :: SetAbstractFieldParam PUBLIC :: AbstractFieldCheckEssentialParam +PUBLIC :: AbstractField_ +PUBLIC :: AbstractFieldInitiate2 +PUBLIC :: FIELD_TYPE_NAME !---------------------------------------------------------------------------- ! AbstractField_ @@ -106,6 +109,9 @@ MODULE AbstractField_Class !! and BlockMatrixField CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE(aField_checkEssentialParam), DEFERRED, PUBLIC, PASS(obj) :: & & checkEssentialParam !! check essential parameters @@ -120,6 +126,9 @@ MODULE AbstractField_Class GENERIC, PUBLIC :: Copy => Initiate2 PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => aField_Deallocate !! Deallocate the field + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => aField_Display !! Display the field PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => aField_Import @@ -129,8 +138,10 @@ MODULE AbstractField_Class PROCEDURE, PUBLIC, PASS(obj) :: WriteData_vtk => afield_WriteData_vtk PROCEDURE, PUBLIC, PASS(obj) :: WriteData_hdf5 => afield_WriteData_hdf5 GENERIC, PUBLIC :: WriteData => WriteData_vtk, WriteData_hdf5 + + ! GET: + ! @GetMethods PROCEDURE, PASS(obj), NON_OVERRIDABLE, PUBLIC :: GetParam - PROCEDURE, PASS(obj), NON_OVERRIDABLE, PUBLIC :: SetParam PROCEDURE, PUBLIC, PASS(obj) :: GetTotalPhysicalVars & & => aField_GetTotalPhysicalVars !! Returns the total number of physical variables @@ -153,7 +164,8 @@ MODULE AbstractField_Class !! Returns the total number of degree of freedoms !! This is same as calling Size !! INFO: This routine should be implemented by child classes - PROCEDURE, PUBLIC, PASS(obj) :: GetTotalVertexDOF => aField_GetTotalVertexDOF + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalVertexDOF => & + & aField_GetTotalVertexDOF !! Returns the total number of vertex degree of freedoms !! INFO: This routine should be implemented by child classes PROCEDURE, PUBLIC, PASS(obj) :: GetTotalEdgeDOF => aField_GetTotalEdgeDOF @@ -169,12 +181,15 @@ MODULE AbstractField_Class & => aField_isConstant !! It returns true if the field is constant field !! INFO: This routine should be implemented by child classes -END TYPE AbstractField_ -PUBLIC :: AbstractField_ + ! SET: + ! @SetMethods + PROCEDURE, PASS(obj), NON_OVERRIDABLE, PUBLIC :: SetParam + +END TYPE AbstractField_ !---------------------------------------------------------------------------- -! checkEssentialParam@Constructor +! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -190,7 +205,7 @@ END SUBROUTINE aField_CheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- -! Initiate +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -207,7 +222,7 @@ END SUBROUTINE aField_Initiate1 END INTERFACE !---------------------------------------------------------------------------- -! CheckEssentialParam +! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- INTERFACE @@ -219,7 +234,7 @@ END SUBROUTINE AbstractFieldCheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- -! SetAbstractFieldParam +! SetAbstractFieldParam@ConstructorMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -227,8 +242,8 @@ END SUBROUTINE AbstractFieldCheckEssentialParam ! summary: Set AbstractField_ parameters INTERFACE - MODULE SUBROUTINE SetAbstractFieldParam(param, prefix, name, engine, fieldType, & - & comm, local_n, global_n) + MODULE SUBROUTINE SetAbstractFieldParam(param, prefix, name, engine, & + & fieldType, comm, local_n, global_n) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: prefix !! prefix @@ -251,7 +266,7 @@ END SUBROUTINE SetAbstractFieldParam END INTERFACE !---------------------------------------------------------------------------- -! Initiate +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -268,14 +283,14 @@ END SUBROUTINE AbstractFieldInitiate END INTERFACE !---------------------------------------------------------------------------- -! InitiateByCopy +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 29 Sept 2021 ! summary: Initiate by copying other fields, and different options -INTERFACE +INTERFACE AbstractFieldInitiate2 MODULE SUBROUTINE aField_Initiate2(obj, obj2, copyFull, copyStructure, & & usePointer) CLASS(AbstractField_), INTENT(INOUT) :: obj @@ -284,16 +299,10 @@ MODULE SUBROUTINE aField_Initiate2(obj, obj2, copyFull, copyStructure, & LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer END SUBROUTINE aField_Initiate2 -END INTERFACE - -INTERFACE AbstractFieldInitiate2 - MODULE PROCEDURE aField_Initiate2 END INTERFACE AbstractFieldInitiate2 -PUBLIC :: AbstractFieldInitiate2 - !---------------------------------------------------------------------------- -! InitiateByCopy +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -310,26 +319,54 @@ END SUBROUTINE aField_Initiate3 END INTERFACE !---------------------------------------------------------------------------- -! Display +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +INTERFACE AbstractFieldDeallocate + MODULE SUBROUTINE aField_Deallocate(obj) + CLASS(AbstractField_), INTENT(INOUT) :: obj + END SUBROUTINE aField_Deallocate +END INTERFACE AbstractFieldDeallocate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +INTERFACE + MODULE PURE FUNCTION FIELD_TYPE_NUMBER(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION FIELD_TYPE_NUMBER +END INTERFACE + +!---------------------------------------------------------------------------- +! !---------------------------------------------------------------------------- INTERFACE + MODULE PURE FUNCTION FIELD_TYPE_NAME(id) RESULT(Ans) + INTEGER(I4B), INTENT(IN) :: id + CHARACTER(20) :: ans + END FUNCTION FIELD_TYPE_NAME +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +INTERFACE AbstractFieldDisplay MODULE SUBROUTINE aField_Display(obj, msg, unitNo) CLASS(AbstractField_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo END SUBROUTINE aField_Display -END INTERFACE - -INTERFACE AbstractFieldDisplay - MODULE PROCEDURE aField_Display END INTERFACE AbstractFieldDisplay !---------------------------------------------------------------------------- -! IMPORT +! IMPORT@IOMethods !---------------------------------------------------------------------------- -INTERFACE +INTERFACE AbstractFieldImport MODULE SUBROUTINE aField_Import(obj, hdf5, group, dom, domains) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 @@ -337,98 +374,55 @@ MODULE SUBROUTINE aField_Import(obj, hdf5, group, dom, domains) TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE aField_Import -END INTERFACE - -INTERFACE AbstractFieldImport - MODULE PROCEDURE aField_Import END INTERFACE AbstractFieldImport !---------------------------------------------------------------------------- -! Export +! Export@IOMethods !---------------------------------------------------------------------------- -INTERFACE +INTERFACE AbstractFieldExport MODULE SUBROUTINE aField_Export(obj, hdf5, group) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE aField_Export -END INTERFACE - -INTERFACE AbstractFieldExport - MODULE PROCEDURE aField_Export END INTERFACE AbstractFieldExport !---------------------------------------------------------------------------- -! Export -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE aField_Deallocate(obj) - CLASS(AbstractField_), INTENT(INOUT) :: obj - END SUBROUTINE aField_Deallocate -END INTERFACE - -INTERFACE AbstractFieldDeallocate - MODULE PROCEDURE aField_Deallocate -END INTERFACE AbstractFieldDeallocate - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -INTERFACE - MODULE PURE FUNCTION FIELD_TYPE_NUMBER(name) RESULT(Ans) - CHARACTER(*), INTENT(IN) :: name - INTEGER(I4B) :: ans - END FUNCTION FIELD_TYPE_NUMBER -END INTERFACE - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -INTERFACE - MODULE PURE FUNCTION FIELD_TYPE_NAME(id) RESULT(Ans) - INTEGER(I4B), INTENT(IN) :: id - CHARACTER(20) :: ans - END FUNCTION FIELD_TYPE_NAME -END INTERFACE - -PUBLIC :: FIELD_TYPE_NAME - -!---------------------------------------------------------------------------- -! +! WriteData@IOMethods !---------------------------------------------------------------------------- -INTERFACE +INTERFACE AbstractFieldWriteData MODULE SUBROUTINE aField_WriteData_hdf5(obj, hdf5, group) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE aField_WriteData_hdf5 -END INTERFACE +END INTERFACE AbstractFieldWriteData !---------------------------------------------------------------------------- -! +! WriteData@IOMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. ! date: 2023-11-24 ! summary: Export data in vrkfile -INTERFACE - MODULE SUBROUTINE aField_WriteData_vtk(obj, vtk, group) +INTERFACE AbstractFieldWriteData + MODULE SUBROUTINE aField_WriteData_vtk(obj, vtk) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(VTKFile_), INTENT(INOUT) :: vtk - CHARACTER(*), INTENT(IN) :: group END SUBROUTINE aField_WriteData_vtk -END INTERFACE +END INTERFACE AbstractFieldWriteData !---------------------------------------------------------------------------- -! +! SetParam@SetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-25 +! summary: Set field variables of abstract field + INTERFACE MODULE SUBROUTINE SetParam(obj, & & isInitiated, & @@ -472,9 +466,13 @@ END SUBROUTINE SetParam END INTERFACE !---------------------------------------------------------------------------- -! +! GetParam@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-25 +! summary: Get the field variables + INTERFACE MODULE SUBROUTINE GetParam(obj, & & isInitiated, & @@ -518,7 +516,7 @@ END SUBROUTINE GetParam END INTERFACE !---------------------------------------------------------------------------- -! GetTotalPhysicalVars +! GetTotalPhysicalVars@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -533,7 +531,7 @@ END FUNCTION aField_GetTotalPhysicalVars END INTERFACE !---------------------------------------------------------------------------- -! GetPhysicalNames +! GetPhysicalNames@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -548,7 +546,7 @@ END SUBROUTINE aField_GetPhysicalNames END INTERFACE !---------------------------------------------------------------------------- -! GetSpaceCompo +! GetSpaceCompo@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -566,7 +564,7 @@ END FUNCTION aField_GetSpaceCompo END INTERFACE !---------------------------------------------------------------------------- -! GetTimeCompo +! GetTimeCompo@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -582,7 +580,7 @@ END FUNCTION aField_GetTimeCompo END INTERFACE !---------------------------------------------------------------------------- -! GetStorageFMT +! GetStorageFMT@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -597,7 +595,7 @@ END FUNCTION aField_GetStorageFMT END INTERFACE !---------------------------------------------------------------------------- -! GetTotalDOF +! GetTotalDOF@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -616,7 +614,7 @@ END FUNCTION aField_GetTotalDOF END INTERFACE !---------------------------------------------------------------------------- -! GetTotalVertexDOF +! GetTotalVertexDOF@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -632,7 +630,7 @@ END FUNCTION aField_GetTotalVertexDOF END INTERFACE !---------------------------------------------------------------------------- -! GetTotalEdgeDOF +! GetTotalEdgeDOF@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -648,7 +646,7 @@ END FUNCTION aField_GetTotalEdgeDOF END INTERFACE !---------------------------------------------------------------------------- -! GetTotalFaceDOF +! GetTotalFaceDOF@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -664,7 +662,7 @@ END FUNCTION aField_GetTotalFaceDOF END INTERFACE !---------------------------------------------------------------------------- -! GetTotalCellDOF +! GetTotalCellDOF@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -680,7 +678,7 @@ END FUNCTION aField_GetTotalCellDOF END INTERFACE !---------------------------------------------------------------------------- -! isConstant +! isConstant@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. diff --git a/src/submodules/AbstractField/CMakeLists.txt b/src/submodules/AbstractField/CMakeLists.txt index e78ab68ba..94a64f92a 100644 --- a/src/submodules/AbstractField/CMakeLists.txt +++ b/src/submodules/AbstractField/CMakeLists.txt @@ -1,22 +1,24 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# 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}/AbstractField_Class@Methods.F90 -) \ No newline at end of file +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} + PRIVATE ${src_path}/AbstractField_Class@ConstructorMethods.F90 + ${src_path}/AbstractField_Class@IOMethods.F90 + ${src_path}/AbstractField_Class@GetMethods.F90 + ${src_path}/AbstractField_Class@SetMethods.F90) diff --git a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..14c7cffbe --- /dev/null +++ b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 @@ -0,0 +1,238 @@ +! 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(AbstractField_Class) ConstructorMethods +USE BaseMethod +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractFieldCheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "AbstractFieldCheckEssentialParam()" +TYPE(String) :: astr +TYPE(String), ALLOCATABLE :: essentialParam(:) +INTEGER(I4B) :: ii + +astr = "/name/engine/fieldType/comm/local_n/global_n" +CALL astr%Split(essentialParam, sep="/") +CALL CheckEssentialParam( & + & obj=param, & + & keys=essentialParam, & + & prefix=prefix, & + & myName=myName, & + & modName=modName) +! INFO: CheckEssentialParam param is defined in easifemClasses FPL_Method + +IF (ALLOCATED(essentialParam)) THEN + DO ii = 1, SIZE(essentialParam) + essentialParam(ii) = "" + END DO + DEALLOCATE (essentialParam) +END IF +astr = "" +END PROCEDURE AbstractFieldCheckEssentialParam + +!---------------------------------------------------------------------------- +! SetScalarFieldParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetAbstractFieldParam +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr +CHARACTER(*), PARAMETER :: myName = "SetAbstractFieldParam()" +LOGICAL(LGT) :: isSublist + +sublist => NULL() + +! Create a new sublist +isSublist = param%isSubList(prefix) + +IF (isSublist) THEN + ierr = param%GetSubList(key=prefix, sublist=sublist) + IF (ierr .NE. 0) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + END IF +ELSE + sublist => param%NewSubList(key=prefix) +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF + +CALL Set(obj=sublist, datatype="Char", prefix=prefix, key="name", VALUE=name) + +CALL Set(obj=sublist, datatype="Char", prefix=prefix, key="engine", & + & VALUE=engine) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="fieldType", & + & VALUE=input(option=fieldType, default=FIELD_TYPE_NORMAL)) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="comm", & + & VALUE=input(option=fieldType, default=0_I4B)) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="local_n", & + & VALUE=input(option=local_n, default=0_I4B)) + +CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="global_n", & + & VALUE=input(option=global_n, default=0_I4B)) + +sublist => NULL() +END PROCEDURE SetAbstractFieldParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractFieldInitiate +CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate()" +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr + +! main +sublist => NULL() +ierr = param%GetSubList(key=prefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +! NOTE: We should not call deallocate in abstract classes. +! This is because, in concrete classes we may set some +! parameters before calling this method. +! All those parameters will be gone if we call deallocate +! here. +! CALL obj%DEALLOCATE() + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF + +obj%isInitiated = .TRUE. +CALL GetValue(obj=sublist, prefix=prefix, key="fieldType", VALUE=obj%fieldType) +CALL GetValue(obj=sublist, prefix=prefix, key="name", VALUE=obj%name) +CALL GetValue(obj=sublist, prefix=prefix, key="engine", VALUE=obj%engine) +CALL GetValue(obj=sublist, prefix=prefix, key="comm", VALUE=obj%comm) +CALL GetValue(obj=sublist, prefix=prefix, key="global_n", VALUE=obj%global_n) +CALL GetValue(obj=sublist, prefix=prefix, key="local_n", VALUE=obj%local_n) +obj%domain => dom +sublist => NULL() +END PROCEDURE AbstractFieldInitiate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Initiate2 +CHARACTER(*), PARAMETER :: myName = "aField_Initiate2" +INTEGER(I4B) :: ii, tsize + +IF (.NOT. obj2%isInitiated .OR. obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Either obj is already initiated or obj2 is not initiated!') +END IF +obj%isInitiated = obj2%isInitiated +obj%fieldType = obj2%fieldType +obj%name = obj2%name +obj%engine = obj2%engine +obj%comm = obj2%comm +obj%myRank = obj2%myRank +obj%numProcs = obj2%numProcs +obj%global_n = obj2%global_n +obj%local_n = obj2%local_n +obj%is = obj2%is +obj%ie = obj2%ie +obj%lis_ptr = obj2%lis_ptr +obj%domain => obj2%domain +IF (ALLOCATED(obj2%domains)) THEN + tsize = SIZE(obj2%domains) + ALLOCATE (obj%domains(tsize)) + DO ii = 1, tsize + obj%domains(ii)%ptr => obj2%domains(ii)%ptr + END DO +END IF +END PROCEDURE aField_Initiate2 + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Deallocate +INTEGER(I4B) :: ii +obj%name = "" +obj%engine = "" +obj%isInitiated = .FALSE. +obj%fieldType = FIELD_TYPE_NORMAL +obj%comm = 0 +obj%myRank = 0 +obj%numProcs = 1 +obj%global_n = 0 +obj%local_n = 0 +obj%is = 0 +obj%ie = 0 +obj%lis_ptr = 0 +obj%domain => NULL() +IF (ALLOCATED(obj%domains)) THEN + DO ii = 1, SIZE(obj%domains) + obj%domains(ii)%ptr => NULL() + END DO + DEALLOCATE (obj%domains) +END IF +END PROCEDURE aField_Deallocate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE FIELD_TYPE_NUMBER +SELECT CASE (TRIM(name)) +CASE ("NORMAL") + ans = FIELD_TYPE_NORMAL +CASE ("CONSTANT") + ans = FIELD_TYPE_CONSTANT +CASE ("CONSTANT_SPACE") + ans = FIELD_TYPE_CONSTANT_SPACE +CASE ("CONSTANT_TIME") + ans = FIELD_TYPE_CONSTANT_TIME +END SELECT +END PROCEDURE FIELD_TYPE_NUMBER + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE FIELD_TYPE_NAME +! +SELECT CASE (id) +CASE (FIELD_TYPE_NORMAL) + ans = "NORMAL" +CASE (FIELD_TYPE_CONSTANT) + ans = "CONSTANT" +CASE (FIELD_TYPE_CONSTANT_SPACE) + ans = "CONSTANT_SPACE" +CASE (FIELD_TYPE_CONSTANT_TIME) + ans = "CONSTANT_TIME" +END SELECT +END PROCEDURE FIELD_TYPE_NAME + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 new file mode 100644 index 000000000..ade189358 --- /dev/null +++ b/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 @@ -0,0 +1,196 @@ +! 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(AbstractField_Class) GetMethods +USE BaseMethod +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE GetParam +USE AbstractNodeField_Class, ONLY: AbstractNodeField_ +USE AbstractMatrixField_Class, ONLY: AbstractMatrixField_ + +CHARACTER(*), PARAMETER :: myName = "GetParam" +INTEGER(I4B) :: ii + +IF (PRESENT(isInitiated)) isInitiated = obj%isInitiated +IF (PRESENT(fieldType)) fieldType = obj%fieldType +IF (PRESENT(name)) name = obj%name%chars() +IF (PRESENT(engine)) engine = obj%engine%chars() +IF (PRESENT(comm)) comm = obj%comm +IF (PRESENT(myRank)) myRank = obj%myRank +IF (PRESENT(numProcs)) numProcs = obj%numProcs +IF (PRESENT(global_n)) global_n = obj%global_n +IF (PRESENT(local_n)) local_n = obj%local_n +IF (PRESENT(is)) is = obj%is +IF (PRESENT(ie)) ie = obj%ie +IF (PRESENT(lis_ptr)) lis_ptr = obj%lis_ptr +IF (PRESENT(domain)) domain => obj%domain + +IF (PRESENT(domains)) THEN + IF (.NOT. ALLOCATED(obj%domains)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'AbstractField_::obj%domains is not allocated ') + END IF + + IF (SIZE(obj%domains) .NE. SIZE(domains)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'AbstractField_::obj%domains size is not same as size of domains') + END IF + + DO ii = 1, SIZE(domains) + domains(ii)%ptr => obj%domains(ii)%ptr + END DO +END IF + +SELECT TYPE (obj) +CLASS IS (AbstractNodeField_) + IF (PRESENT(tSize)) tSize = obj%tSize + IF (PRESENT(realVec)) realVec = obj%realVec + IF (PRESENT(dof)) dof = obj%dof +CLASS IS (AbstractMatrixField_) + IF (PRESENT(isPMatInitiated)) isPMatInitiated = obj%isPMatInitiated +END SELECT +END PROCEDURE GetParam + +!---------------------------------------------------------------------------- +! GetTotalPhysicalVars +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalPhysicalVars +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalPhysicalVars()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') +END PROCEDURE aField_GetTotalPhysicalVars + +!---------------------------------------------------------------------------- +! aField_GetPhysicalNames +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetPhysicalNames +CHARACTER(*), PARAMETER :: myName = "aField_GetNames()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & + & " child classes.") +END PROCEDURE aField_GetPhysicalNames + +!---------------------------------------------------------------------------- +! GetSpaceCompo +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetSpaceCompo +CHARACTER(*), PARAMETER :: myName = "aField_GetSpaceCompo()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & + & " child classes.") +END PROCEDURE aField_GetSpaceCompo + +!---------------------------------------------------------------------------- +! GetTimeCompo +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTimeCompo +CHARACTER(*), PARAMETER :: myName = "aField_GetTimeCompo" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & + & " child classes.") +END PROCEDURE aField_GetTimeCompo + +!---------------------------------------------------------------------------- +! GetStorageFMT +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetStorageFMT +CHARACTER(*), PARAMETER :: myName = "aField_GetStorageFMT" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & + & " child classes.") +END PROCEDURE aField_GetStorageFMT + +!---------------------------------------------------------------------------- +! GetTotalDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalDOF()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & + & ' child classes') +END PROCEDURE aField_GetTotalDOF + +!---------------------------------------------------------------------------- +! GetTotalVertexDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalVertexDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalVertexDOF()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') +END PROCEDURE aField_GetTotalVertexDOF + +!---------------------------------------------------------------------------- +! GetTotalEdgeDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalEdgeDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalEdgeDOF()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') +END PROCEDURE aField_GetTotalEdgeDOF + +!---------------------------------------------------------------------------- +! GetTotalFaceDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalFaceDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalFaceDOF()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') +END PROCEDURE aField_GetTotalFaceDOF + +!---------------------------------------------------------------------------- +! GetTotalCellDOF +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetTotalCellDOF +CHARACTER(*), PARAMETER :: myName = "aField_GetTotalCellDOF()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& + & 'child classes') +END PROCEDURE aField_GetTotalCellDOF + +!---------------------------------------------------------------------------- +! isConstant +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_isConstant +IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN + ans = .TRUE. +ELSE + ans = .FALSE. +END IF +END PROCEDURE aField_isConstant + +END SUBMODULE GetMethods diff --git a/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 new file mode 100644 index 000000000..241908c01 --- /dev/null +++ b/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 @@ -0,0 +1,319 @@ +! 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(AbstractField_Class) IOMethods +USE BaseMethod +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Display +INTEGER(I4B) :: ii + +CALL Display("#"//TRIM(msg), unitNo=unitNo) + +IF (obj%isInitiated) THEN + CALL Display("# isInitiated : TRUE", unitNo=unitNo) +ELSE + CALL Display("# isInitiated : FALSE, Nothing to Display!", unitNo=unitNo) + RETURN +END IF + +CALL Display(obj%name//'', msg="# name : ", unitNo=unitNo) + +IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN + CALL Display("# fieldType : CONSTANT", unitNo=unitNo) +ELSE + CALL Display("# fieldType : NORMAL", unitNo=unitNo) +END IF + +CALL Display(obj%engine, msg='# engine : ', unitNo=unitNo) +CALL Display(obj%comm, msg='# comm: ', unitNo=unitNo) +CALL Display(obj%myRank, msg='# myRank: ', unitNo=unitNo) +CALL Display(obj%numProcs, msg='# numProcs: ', unitNo=unitNo) +CALL Display(obj%global_n, msg='# global_n: ', unitNo=unitNo) +CALL Display(obj%local_n, msg='# local_n: ', unitNo=unitNo) +CALL Display(obj%is, msg='# is: ', unitNo=unitNo) +CALL Display(obj%ie, msg='# ie: ', unitNo=unitNo) +CALL Display(obj%lis_ptr, msg='# lis_ptr: ', unitNo=unitNo) + +IF (ASSOCIATED(obj%domain)) THEN + CALL Display("# domain : ASSOCIATED", unitNo=unitNo) +ELSE + CALL Display("# domain : NOT ASSOCIATED", unitNo=unitNo) +END IF +! +IF (ALLOCATED(obj%domains)) THEN + CALL Display("# domains : ALLOCATED [" & + & //TOSTRING(SIZE(obj%domains)) & + & //"]", unitNo=unitNo) + DO ii = 1, SIZE(obj%domains) + IF (ASSOCIATED(obj%domains(ii)%ptr)) THEN + CALL Display("# domains("//TOSTRING(ii) & + & //")%ptr : ASSOCIATED", unitNo=unitNo) + ELSE + CALL Display("# domains("//TOSTRING(ii) & + & //")%ptr : NOT ASSOCIATED", unitNo=unitNo) + END IF + END DO +ELSE + CALL Display("# domains : NOT ALLOCATED", unitNo=unitNo) +END IF + +END PROCEDURE aField_Display + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_WriteData_hdf5 +CHARACTER(*), PARAMETER :: myName = "aField_WriteData_hdf5" +CALL e%raiseError(modName//'::'//myName//' - '// & + & 'This method should be implemented by children of AbstractField_') +END PROCEDURE aField_WriteData_hdf5 + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_WriteData_vtk +CHARACTER(*), PARAMETER :: myName = "aField_WriteData_vtk" +CALL e%raiseError(modName//'::'//myName//' - '// & + & 'This method should be implemented by children of AbstractField_') +END PROCEDURE aField_WriteData_vtk + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Export +CHARACTER(*), PARAMETER :: myName = "aField_Export" +TYPE(String) :: dname, matprop + +IF (.NOT. obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Instnace of MatrixField_ is not initiated') +END IF + +! Check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file is not opened') +END IF + +! Check +IF (.NOT. hdf5%isWrite()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file does not have write permission') +END IF + +! fieldType +dname = TRIM(group)//"/fieldType" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=STRING(FIELD_TYPE_NAME(obj%fieldType))) + +! name +dname = TRIM(group)//"/name" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%name) + +! engine +dname = TRIM(group)//"/engine" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%engine) + +! comm +dname = TRIM(group)//"/comm" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%comm) + +! myRank +dname = TRIM(group)//"/myRank" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%myRank) + +! numProcs +dname = TRIM(group)//"/numProcs" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%numProcs) + +! local_n +dname = TRIM(group)//"/local_n" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%local_n) + +! global_n +dname = TRIM(group)//"/global_n" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%global_n) + +! is +dname = TRIM(group)//"/is" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%is) + +! ie +dname = TRIM(group)//"/ie" +CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & + & vals=obj%ie) + +END PROCEDURE aField_Export + +!---------------------------------------------------------------------------- +! aField_Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Import +CHARACTER(*), PARAMETER :: myName = "aField_Import" +TYPE(String) :: strval, dsetname, matrixProp + +CALL e%raiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') + +! main program +IF (obj%isInitiated) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'The instance of AbstractField_ is already initiated') +END IF + +! Check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file is not opened') +END IF + +! Check +IF (.NOT. hdf5%isRead()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'HDF5 file does not have read permission') +END IF + +! fieldType +dsetname = TRIM(group)//"/fieldType" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + obj%fieldType = FIELD_TYPE_NUMBER(strval%chars()) +ELSE + obj%fieldType = FIELD_TYPE_NORMAL +END IF + +! name +dsetname = TRIM(group)//"/name" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'The dataset name should be present') +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%name) +END IF + +! engine +dsetname = TRIM(group)//"/engine" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%engine = "NATIVE_SERIAL" +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%engine) +END IF + +! comm +dsetname = TRIM(group)//"/comm" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%comm = 0 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%comm) +END IF + +! myRank +dsetname = TRIM(group)//"/myRank" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%myRank = 0 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%myRank) +END IF + +! numProcs +dsetname = TRIM(group)//"/numProcs" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%numProcs = 1 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%numProcs) +END IF + +! global_n +dsetname = TRIM(group)//"/global_n" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%global_n = 1 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%global_n) +END IF + +! local_n +dsetname = TRIM(group)//"/local_n" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%local_n = 1 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%local_n) +END IF + +! is +dsetname = TRIM(group)//"/is" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%is = 1 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%is) +END IF + +! ie +dsetname = TRIM(group)//"/ie" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + obj%ie = 1 +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%ie) +END IF + +IF (ASSOCIATED(obj%domain)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'obj%domain is associated, deallocate first') +END IF + +IF (ALLOCATED(obj%domains)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & 'obj%domains is allocated, deallocate first') +END IF + +IF (PRESENT(dom)) THEN + obj%domain => dom +ELSE IF (PRESENT(domains)) THEN + ALLOCATE (obj%domains(2)) + obj%domains(1)%ptr => domains(1)%ptr + obj%domains(2)%ptr => domains(2)%ptr +ELSE + CALL e%raiseError(modName//'::'//myName//" - "// & + & "For non-rectangle matrix dom should be present, "// & + & "for rectangle matrix matrix domains should be present") +END IF + +obj%isInitiated = .TRUE. + +CALL e%raiseInformation(modName//'::'//myName//' - '// & +& '[END] Import()') + +END PROCEDURE aField_Import + +END SUBMODULE IOMethods diff --git a/src/submodules/AbstractField/src/AbstractField_Class@SetMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@SetMethods.F90 new file mode 100644 index 000000000..26579783e --- /dev/null +++ b/src/submodules/AbstractField/src/AbstractField_Class@SetMethods.F90 @@ -0,0 +1,74 @@ +! 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(AbstractField_Class) SetMethods +USE BaseMethod +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetParam +USE AbstractNodeField_Class, ONLY: AbstractNodeField_ +USE AbstractMatrixField_Class, ONLY: AbstractMatrixField_ + +CHARACTER(*), PARAMETER :: myName = "SetParam" +INTEGER(I4B) :: ii + +IF (PRESENT(isInitiated)) obj%isInitiated = isInitiated +IF (PRESENT(fieldType)) obj%fieldType = fieldType +IF (PRESENT(name)) obj%name = TRIM(name) +IF (PRESENT(engine)) obj%engine = TRIM(engine) +IF (PRESENT(comm)) obj%comm = comm +IF (PRESENT(myRank)) obj%myRank = myRank +IF (PRESENT(numProcs)) obj%numProcs = numProcs +IF (PRESENT(global_n)) obj%global_n = global_n +IF (PRESENT(local_n)) obj%local_n = local_n +IF (PRESENT(is)) obj%is = is +IF (PRESENT(ie)) obj%ie = ie +IF (PRESENT(lis_ptr)) obj%lis_ptr = lis_ptr +IF (PRESENT(domain)) obj%domain => domain +IF (PRESENT(domains)) THEN + IF (.NOT. ALLOCATED(obj%domains)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: AbstractField_::Obj%domains is not allocated ') + END IF + + IF (SIZE(obj%domains) .NE. SIZE(domains)) THEN + CALL e%raiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: AbstractField_::Obj%domains '// & + & CHAR_LF//'size is not same as size of domains') + END IF + + DO ii = 1, SIZE(domains) + obj%domains(ii)%ptr => domains(ii)%ptr + END DO +END IF + +SELECT TYPE (obj) +CLASS IS (AbstractNodeField_) + IF (PRESENT(tSize)) obj%tSize = tSize + IF (PRESENT(realVec)) obj%realVec = realVec + IF (PRESENT(dof)) obj%dof = dof +CLASS IS (AbstractMatrixField_) + IF (PRESENT(isPMatInitiated)) obj%isPMatInitiated = isPMatInitiated +END SELECT +END PROCEDURE SetParam + +END SUBMODULE SetMethods From ed9fad30a27f1323bc6a7c5e34c73b1d3d92d05a Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:16:28 +0900 Subject: [PATCH 027/117] Update AbstractField_Class.F90 Improving GetPhysicalNames method by adding inout to ans. --- src/modules/AbstractField/src/AbstractField_Class.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index 2adf5b6d9..f6ec1a755 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -541,7 +541,7 @@ END FUNCTION aField_GetTotalPhysicalVars INTERFACE MODULE SUBROUTINE aField_GetPhysicalNames(obj, ans) CLASS(AbstractField_), INTENT(IN) :: obj - CHARACTER(*) :: ans(:) + CHARACTER(*), INTENT(INOUT) :: ans(:) END SUBROUTINE aField_GetPhysicalNames END INTERFACE From 0e7199fd0b1cc322b445d66f43f215e2b10164ff Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:20:12 +0900 Subject: [PATCH 028/117] Update AbstractNodeField_Class.F90 - Removing group argument from WriteData_VTK - Adding GetPhysicalNames Method --- .../src/AbstractNodeField_Class.F90 | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index 35c57514a..abdb92024 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -14,7 +14,7 @@ MODULE AbstractNodeField_Class USE GlobalData -USE BaseType +USE BaSetype USE RealVector_Method USE DOF_Method USE AbstractField_Class @@ -37,8 +37,7 @@ MODULE AbstractNodeField_Class PUBLIC :: AbstractNodeFieldGetSingle PUBLIC :: AbstractNodeFieldInitiate PUBLIC :: AbstractNodeFieldSetParam - -CHARACTER(*), PARAMETER :: modName = "AbstractField_Class" +CHARACTER(*), PARAMETER :: modName = "AbstractNodeField_Class" CHARACTER(*), PARAMETER :: myprefix = "AbstractNodeField" !---------------------------------------------------------------------------- @@ -111,8 +110,10 @@ MODULE AbstractNodeField_Class !! Returns the L2 norm PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => anf_GetSingle !! Get single entry + PROCEDURE, PUBLIC, PASS(obj) :: GetPhysicalNames => anf_GetPhysicalNames + !! Get physical names - ! SET: + ! Set: ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => anf_SetSingle !! Set single entry @@ -221,10 +222,9 @@ END SUBROUTINE anf_Export ! summary: Export data in vrkfile INTERFACE AbstractNodeWriteData - MODULE SUBROUTINE anf_WriteData_vtk(obj, vtk, group) + MODULE SUBROUTINE anf_WriteData_vtk(obj, vtk) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj TYPE(VTKFile_), INTENT(INOUT) :: vtk - CHARACTER(*), INTENT(IN) :: group END SUBROUTINE anf_WriteData_vtk END INTERFACE AbstractNodeWriteData @@ -244,7 +244,7 @@ END FUNCTION anf_GetPointer END INTERFACE AbstractNodeFieldGetPointer !---------------------------------------------------------------------------- -! anf_Initiate3 +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -281,7 +281,7 @@ END SUBROUTINE anf_Initiate2 END INTERFACE AbstractNodeFieldInitiate2 !---------------------------------------------------------------------------- -! anf_Initiate3 +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -297,7 +297,7 @@ END SUBROUTINE anf_Initiate3 END INTERFACE !---------------------------------------------------------------------------- -! Deallocate +! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -315,7 +315,7 @@ END SUBROUTINE anf_Deallocate END INTERFACE AbstractNodeFieldDeallocate !---------------------------------------------------------------------------- -! Norm2 +! Norm2@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -338,22 +338,22 @@ END FUNCTION anf_Norm2 ! summary: Set single entry INTERFACE - MODULE SUBROUTINE anf_setSingle(obj, indx, VALUE, scale, & + MODULE SUBROUTINE anf_SetSingle(obj, indx, VALUE, scale, & & addContribution) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: indx REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE anf_setSingle + END SUBROUTINE anf_SetSingle END INTERFACE INTERFACE AbstractNodeFieldSetSingle - MODULE PROCEDURE anf_setSingle + MODULE PROCEDURE anf_SetSingle END INTERFACE AbstractNodeFieldSetSingle !---------------------------------------------------------------------------- -! GetSingle@Methods +! GetSingle@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -372,6 +372,21 @@ END SUBROUTINE anf_GetSingle MODULE PROCEDURE anf_GetSingle END INTERFACE AbstractNodeFieldGetSingle +!---------------------------------------------------------------------------- +! GetPhysicalNames@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns the names of physical variables + +INTERFACE + MODULE SUBROUTINE anf_GetPhysicalNames(obj, ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + CHARACTER(*), INTENT(INOUT) :: ans(:) + END SUBROUTINE anf_GetPhysicalNames +END INTERFACE + !---------------------------------------------------------------------------- ! Size !---------------------------------------------------------------------------- From 72275c8dac5e3150d422e90fae1fba6f316e586b Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:20:52 +0900 Subject: [PATCH 029/117] Update AbstractNodeField_Class@ConstructorMethods.F90 Minor formatting --- ...ractNodeField_Class@ConstructorMethods.F90 | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 index 2c3761e7d..60aa87958 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 @@ -21,63 +21,11 @@ CONTAINS !---------------------------------------------------------------------------- -! Initiate2 -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_Initiate2 -CHARACTER(*), PARAMETER :: myName = "anf_Initiate2" -INTEGER(I4B) :: ii, tsize - -CALL obj%DEALLOCATE() -CALL AbstractFieldInitiate2( & - & obj=obj, & - & obj2=obj2, & - & copyFull=copyFull, & - & copyStructure=copyStructure, & - & usePointer=usePointer) - -SELECT TYPE (obj2); CLASS IS (AbstractNodeField_) - obj%tSize = obj2%tSize - obj%realVec = obj2%realVec - obj%dof = obj2%dof -END SELECT - -END PROCEDURE anf_Initiate2 - -!---------------------------------------------------------------------------- -! anf_Initiate3 -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_Initiate3 -CHARACTER(*), PARAMETER :: myName = "anf_Initiate3" -CALL e%raiseError(modName//'::'//myName//" - "// & - & '[IMPLEMENTATION ERROR] :: Initiate3 should be implemented by the'// & - & ' child of AbstractNodeField_') -END PROCEDURE anf_Initiate3 - -!---------------------------------------------------------------------------- -! Deallocate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE anf_Deallocate -CALL AbstractFieldDeallocate(obj) -obj%dof_tPhysicalVars = 0 -obj%dof_storageFMT = NODES_FMT -IF (ALLOCATED(obj%dof_spaceCompo)) DEALLOCATE (obj%dof_spaceCompo) -IF (ALLOCATED(obj%dof_timeCompo)) DEALLOCATE (obj%dof_timeCompo) -IF (ALLOCATED(obj%dof_tNodes)) DEALLOCATE (obj%dof_tNodes) -IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) -obj%tSize = 0 -CALL DEALLOCATE (obj%realVec) -CALL DEALLOCATE (obj%dof) -END PROCEDURE anf_Deallocate - -!---------------------------------------------------------------------------- -! Initiate +! AbstractNodeFieldInitiate !---------------------------------------------------------------------------- MODULE PROCEDURE AbstractNodeFieldInitiate -CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate" +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate()" CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) @@ -132,6 +80,58 @@ END PROCEDURE AbstractNodeFieldInitiate +!---------------------------------------------------------------------------- +! Initiate2 +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Initiate2 +CHARACTER(*), PARAMETER :: myName = "anf_Initiate2" +INTEGER(I4B) :: ii, tsize + +CALL obj%DEALLOCATE() +CALL AbstractFieldInitiate2( & + & obj=obj, & + & obj2=obj2, & + & copyFull=copyFull, & + & copyStructure=copyStructure, & + & usePointer=usePointer) + +SELECT TYPE (obj2); CLASS IS (AbstractNodeField_) + obj%tSize = obj2%tSize + obj%realVec = obj2%realVec + obj%dof = obj2%dof +END SELECT + +END PROCEDURE anf_Initiate2 + +!---------------------------------------------------------------------------- +! anf_Initiate3 +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Initiate3 +CHARACTER(*), PARAMETER :: myName = "anf_Initiate3" +CALL e%raiseError(modName//'::'//myName//" - "// & + & '[IMPLEMENTATION ERROR] :: Initiate3 should be implemented by the'// & + & ' child of AbstractNodeField_') +END PROCEDURE anf_Initiate3 + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Deallocate +CALL AbstractFieldDeallocate(obj) +obj%dof_tPhysicalVars = 0 +obj%dof_storageFMT = NODES_FMT +IF (ALLOCATED(obj%dof_spaceCompo)) DEALLOCATE (obj%dof_spaceCompo) +IF (ALLOCATED(obj%dof_timeCompo)) DEALLOCATE (obj%dof_timeCompo) +IF (ALLOCATED(obj%dof_tNodes)) DEALLOCATE (obj%dof_tNodes) +IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) +obj%tSize = 0 +CALL DEALLOCATE (obj%realVec) +CALL DEALLOCATE (obj%dof) +END PROCEDURE anf_Deallocate + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- From ea9a6e2dbf849ee84471885f16f130863192fe55 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:21:52 +0900 Subject: [PATCH 030/117] Update AbstractNodeField_Class@GetMethods.F90 - Adding GetPhysicalNames method --- .../AbstractNodeField_Class@GetMethods.F90 | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 index be4bd8afa..0af842037 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 @@ -20,6 +20,38 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! GetPhysicalNames +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetPhysicalNames +CHARACTER(*), PARAMETER :: myName = "anf_GetPhysicalNames()" +INTEGER(I4B) :: tnames, aint +LOGICAL(LGT) :: isOK + +IF (ALLOCATED(obj%dof_names_char)) THEN + tnames = SIZE(obj%dof_names_char) + aint = SIZE(ans) + isOK = tnames .EQ. aint + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The size of names ('//tostring(aint)// & + & ') is not same as total physical variables = '//tostring(tnames)) + RETURN + END IF + + DO aint = 1, tnames + ans(aint) (:) = obj%dof_names_char(aint) (1:1) + END DO +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%dof_names_char not'// & + & ' not allocated.') + RETURN +END IF + +END PROCEDURE anf_GetPhysicalNames + !---------------------------------------------------------------------------- ! GetPointer !---------------------------------------------------------------------------- @@ -37,7 +69,7 @@ CALL e%RaiseError(modName//'::'//myName//' - '// & & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& & 'child classes') -! ans = obj%tSize +ans = obj%tSize END PROCEDURE anf_size !---------------------------------------------------------------------------- From 69f4ae09916a9ee29f90a2b2be92b01085e387f3 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:22:16 +0900 Subject: [PATCH 031/117] Update AbstractNodeField_Class@IOMethods.F90 - Implementiing WriteData_VTK method --- .../src/AbstractNodeField_Class@IOMethods.F90 | 130 +++++++++--------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 index 79f0d75cc..5fb735876 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 @@ -111,71 +111,73 @@ ! WriteData !---------------------------------------------------------------------------- -MODULE PROCEDURE anf_WriteData +MODULE PROCEDURE anf_WriteData_vtk CHARACTER(*), PARAMETER :: myName = "anf_WriteData()" -LOGICAL(LGT) :: isOK -TYPE(Domain_), POINTER :: dom -TYPE(Mesh_), POINTER :: meshPtr -INTEGER(I4B) :: imesh, tMesh -INTEGER(I4B), ALLOCATABLE :: nptrs(:) - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] WriteData()') -#endif - -isOK = obj%isInitiated -IF (.NOT. isOK) THEN - CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: AbstractNodeField_::obj is not isInitiated.') - RETURN -END IF - -isOK = vtk%isOpen() -IF (.NOT. isOK) THEN - CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') - RETURN -END IF - -isOK = vtk%isWrite() -IF (isOK) THEN - CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: VTKFile_::vtk does not have write access.') - RETURN -END IF - -isOK = ASSOCIATED(obj%domain) .OR. ALLOCATED(obj%domains) -IF (.NOT. isOK) THEN - CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & - & ' or obj%domains not allocated.') - RETURN -END IF - -dom => obj%domain -tMesh = dom%GetTotalMesh() - -DO imesh = 1, tMesh - - meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) - CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) - CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, openTag=.TRUE., & - & content=.TRUE., closeTag=.FALSE.) - CALL vtk%WriteDataArray(location=String('node'), action=String('open')) - nptrs = meshPtr%GetNptrs() - ! CALL sol%Get(globalNode=nptrs, value=fe) - ! CALL vtk%WriteDataArray(name=String("sol"), x=fe, numberOfComponents=1) - CALL vtk%WriteDataArray(location=String('node'), action=String('close')) - CALL vtk%WritePiece() - -END DO - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] WriteData()') -#endif -END PROCEDURE anf_WriteData +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR]') +! LOGICAL(LGT) :: isOK +! TYPE(Domain_), POINTER :: dom +! TYPE(Mesh_), POINTER :: meshPtr +! INTEGER(I4B) :: imesh, tMesh +! INTEGER(I4B), ALLOCATABLE :: nptrs(:) +! +! #ifdef DEBUG_VER +! CALL e%RaiseInformation(modName//'::'//myName//' - '// & +! & '[START] WriteData()') +! #endif +! +! isOK = obj%isInitiated +! IF (.NOT. isOK) THEN +! CALL e%RaiseInformation(modName//'::'//myName//' - '// & +! & '[INTERNAL ERROR] :: AbstractNodeField_::obj is not isInitiated.') +! RETURN +! END IF +! +! isOK = vtk%isOpen() +! IF (.NOT. isOK) THEN +! CALL e%RaiseInformation(modName//'::'//myName//' - '// & +! & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') +! RETURN +! END IF +! +! isOK = vtk%isWrite() +! IF (isOK) THEN +! CALL e%RaiseInformation(modName//'::'//myName//' - '// & +! & '[INTERNAL ERROR] :: VTKFile_::vtk does not have write access.') +! RETURN +! END IF +! +! isOK = ASSOCIATED(obj%domain) .OR. ALLOCATED(obj%domains) +! IF (.NOT. isOK) THEN +! CALL e%RaiseInformation(modName//'::'//myName//' - '// & +! & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & +! & ' or obj%domains not allocated.') +! RETURN +! END IF +! +! dom => obj%domain +! tMesh = dom%GetTotalMesh() +! +! DO imesh = 1, tMesh +! +! meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) +! CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) +! CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, openTag=.TRUE., & +! & content=.TRUE., closeTag=.FALSE.) +! CALL vtk%WriteDataArray(location=String('node'), action=String('open')) +! nptrs = meshPtr%GetNptrs() +! ! CALL sol%Get(globalNode=nptrs, value=fe) +! ! CALL vtk%WriteDataArray(name=String("sol"), x=fe, numberOfComponents=1) +! CALL vtk%WriteDataArray(location=String('node'), action=String('close')) +! CALL vtk%WritePiece() +! +! END DO +! +! #ifdef DEBUG_VER +! CALL e%RaiseInformation(modName//'::'//myName//' - '// & +! & '[END] WriteData()') +! #endif +END PROCEDURE anf_WriteData_vtk !---------------------------------------------------------------------------- ! From 9382137262f8007ad7e42ea61af59efe9ff2cd80 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:22:36 +0900 Subject: [PATCH 032/117] Update AbstractNodeField_Class@SetMethods.F90 Improving SetParam method --- .../src/AbstractNodeField_Class@SetMethods.F90 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 index 2e73420a0..de7c6f789 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@SetMethods.F90 @@ -25,7 +25,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE anf_SetParam -INTEGER(I4B) :: ii +INTEGER(I4B) :: ii, tsize1 IF (PRESENT(dof_tPhysicalVars)) THEN obj%dof_tPhysicalVars = dof_tPhysicalVars @@ -47,11 +47,17 @@ obj%dof_tNodes = dof_tNodes END IF +IF (PRESENT(tSize)) THEN + obj%tsize = tsize +END IF + IF (PRESENT(dof_names_char)) THEN IF (ALLOCATED(obj%dof_names_char)) DEALLOCATE (obj%dof_names_char) - ALLOCATE (obj%dof_names_char(SIZE(dof_names_char))) - DO ii = 1, SIZE(dof_names_char) - obj%dof_names_char(ii) = obj%dof_names_char(ii) + tsize1 = SIZE(dof_names_char) + ALLOCATE (obj%dof_names_char(tsize1)) + + DO ii = 1, tsize1 + obj%dof_names_char(ii) (1:1) = dof_names_char(ii) (1:1) END DO END IF From aac4dd4e8a938804d3a9dea62b2b8d1daaa08dd2 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:23:24 +0900 Subject: [PATCH 033/117] Update ScalarField_Class@ConstructorMethods.F90 Improvement in sField_Initiate1 method. --- .../ScalarField_Class@ConstructorMethods.F90 | 156 +++++++++--------- 1 file changed, 79 insertions(+), 77 deletions(-) diff --git a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 index b039ccbab..a636fea46 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 @@ -54,12 +54,13 @@ TYPE(String) :: astr INTEGER(I4B) :: nsd, tdof, ierr, tNodes TYPE(ParameterList_), POINTER :: sublist +CHARACTER(1) :: names(1) ! main sublist => NULL() ierr = param%GetSubList(key=myprefix, sublist=sublist) -IF (ierr .NE. 0_I4B ) THEN +IF (ierr .NE. 0_I4B) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') END IF @@ -75,6 +76,7 @@ CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) tNodes = dom%GetTotalNodes() tdof = tNodes +names(1) (:) = astr%slice(1, 1) CALL AbstractNodeFieldSetParam(obj=obj, & & dof_tPhysicalVars=1_I4B, & @@ -82,7 +84,7 @@ & dof_spaceCompo=[1_I4B], & & dof_timeCompo=[1_I4B], & & dof_tNodes=[tNodes], & - & dof_names_char=[astr%slice(1, 1)], & + & dof_names_char=names, & & tSize=tdof) nsd = dom%GetNSD() @@ -102,81 +104,81 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE sField_Initiate_old -CHARACTER(*), PARAMETER :: myName = "sField_Initiate1" -INTEGER(I4B) :: ierr, storageFMT -INTEGER(I4B) :: tNodes(1), spaceCompo(1), timeCompo(1) -CHARACTER(:), ALLOCATABLE :: char_var -CHARACTER(1) :: names_char(1) - -! main program -CALL obj%DEALLOCATE() -CALL obj%CheckEssentialParam(param) - -! engine -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) -ierr = param%Get(key=myprefix//"/engine", VALUE=char_var) -obj%engine = char_var -DEALLOCATE (char_var) - -! name -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/name")) :: char_var) -ierr = param%Get(key=myprefix//"/name", VALUE=char_var) -obj%name = char_var -names_char(1) (1:1) = char_var(1:1) -DEALLOCATE (char_var) - -! fieldType -IF (param%isPresent(key=myprefix//"/fieldType")) THEN - ierr = param%Get(key=myprefix//"/fieldType", VALUE=obj%fieldType) -ELSE - obj%fieldType = FIELD_TYPE_NORMAL -END IF - -! comm -ierr = param%Get(key=myprefix//"/comm", VALUE=obj%comm) -ierr = param%Get(key=myprefix//"/global_n", VALUE=obj%global_n) -ierr = param%Get(key=myprefix//"/local_n", VALUE=obj%local_n) - -spaceCompo = [1] -timeCompo = [1] -storageFMT = FMT_NODES -obj%domain => dom -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - tNodes = 1 - obj%tSize = obj%domain%GetTotalNodes() - IF (obj%local_n .EQ. 0) THEN - obj%local_n = tNodes(1) - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = tNodes(1) - END IF -ELSE - tNodes = obj%domain%GetTotalNodes() - obj%tSize = tNodes(1) - IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize - END IF -END IF - -CALL Initiate( & - & obj=obj%dof, & - & tNodes=tNodes, & - & names=names_char, & - & spaceCompo=spaceCompo, & - & timeCompo=timeCompo, & - & storageFMT=storageFMT) - -CALL Initiate(obj%realVec, obj%dof) - -obj%isInitiated = .TRUE. - -IF (ALLOCATED(char_var)) DEALLOCATE (char_var) - +! CHARACTER(*), PARAMETER :: myName = "sField_Initiate1" +! INTEGER(I4B) :: ierr, storageFMT +! INTEGER(I4B) :: tNodes(1), spaceCompo(1), timeCompo(1) +! CHARACTER(:), ALLOCATABLE :: char_var +! CHARACTER(1) :: names_char(1) +! +! ! main program +! CALL obj%DEALLOCATE() +! CALL obj%CheckEssentialParam(param) +! +! ! engine +! ALLOCATE (CHARACTER( & +! & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) +! ierr = param%Get(key=myprefix//"/engine", VALUE=char_var) +! obj%engine = char_var +! DEALLOCATE (char_var) +! +! ! name +! ALLOCATE (CHARACTER( & +! & param%DataSizeInBytes(key=myprefix//"/name")) :: char_var) +! ierr = param%Get(key=myprefix//"/name", VALUE=char_var) +! obj%name = char_var +! names_char(1) (1:1) = char_var(1:1) +! DEALLOCATE (char_var) +! +! ! fieldType +! IF (param%isPresent(key=myprefix//"/fieldType")) THEN +! ierr = param%Get(key=myprefix//"/fieldType", VALUE=obj%fieldType) +! ELSE +! obj%fieldType = FIELD_TYPE_NORMAL +! END IF +! +! ! comm +! ierr = param%Get(key=myprefix//"/comm", VALUE=obj%comm) +! ierr = param%Get(key=myprefix//"/global_n", VALUE=obj%global_n) +! ierr = param%Get(key=myprefix//"/local_n", VALUE=obj%local_n) +! +! spaceCompo = [1] +! timeCompo = [1] +! storageFMT = FMT_NODES +! obj%domain => dom +! IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN +! tNodes = 1 +! obj%tSize = obj%domain%GetTotalNodes() +! IF (obj%local_n .EQ. 0) THEN +! obj%local_n = tNodes(1) +! END IF +! IF (obj%global_n .EQ. 0) THEN +! obj%global_n = tNodes(1) +! END IF +! ELSE +! tNodes = obj%domain%GetTotalNodes() +! obj%tSize = tNodes(1) +! IF (obj%local_n .EQ. 0) THEN +! obj%local_n = obj%tSize +! END IF +! IF (obj%global_n .EQ. 0) THEN +! obj%global_n = obj%tSize +! END IF +! END IF +! +! CALL Initiate( & +! & obj=obj%dof, & +! & tNodes=tNodes, & +! & names=names_char, & +! & spaceCompo=spaceCompo, & +! & timeCompo=timeCompo, & +! & storageFMT=storageFMT) +! +! CALL Initiate(obj%realVec, obj%dof) +! +! obj%isInitiated = .TRUE. +! +! IF (ALLOCATED(char_var)) DEALLOCATE (char_var) +! END PROCEDURE sField_Initiate_old !---------------------------------------------------------------------------- From ce258e21a3341423cf426bec130d6e2c1d8ed810 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:24:01 +0900 Subject: [PATCH 034/117] Update ScalarField_Class.F90 - Adding WriteData_VTK - Minor formating --- .../ScalarField/src/ScalarField_Class.F90 | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index 044f8a0d6..81b65e1d8 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -27,6 +27,7 @@ MODULE ScalarField_Class USE ExceptionHandler_Class, ONLY: e USE FPL, ONLY: ParameterList_ USE HDF5File_Class +USE VTKFile_Class USE Domain_Class USE DirichletBC_Class USE FiniteElement_Class @@ -52,15 +53,20 @@ MODULE ScalarField_Class ! date: 25 June 2021 ! summary: Native vector type ! -!{!pages/docs-api/ScalarField/ScalarField_.md} +!{!pages/docs-api/ScalarField/ScalarField_.md!} TYPE, EXTENDS(AbstractNodeField_) :: ScalarField_ CONTAINS PRIVATE + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & sField_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => sField_Initiate1 FINAL :: sField_Final + + ! SET: + ! @SetMethods PROCEDURE, PASS(obj) :: Set1 => sField_Set1 !! Set single entry PROCEDURE, PASS(obj) :: Set2 => sField_Set2 @@ -87,6 +93,9 @@ MODULE ScalarField_Class & Set5, Set6, Set7, Set8, Set9, Set10, Set11 GENERIC, PUBLIC :: ASSIGNMENT(=) => Set8 !! Set values to a vector + + ! GET: + ! @GetMethods PROCEDURE, PASS(obj) :: Get1 => sField_Get1 !! Get single entry PROCEDURE, PASS(obj) :: Get2 => sField_Get2 @@ -101,13 +110,21 @@ MODULE ScalarField_Class !! Get selected values in FEVariable GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, Get5, Get6, Get7 !! Get the entries of scalar field + + ! SET: + ! @DirichletBCMethods PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC1 PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC2 GENERIC, PUBLIC :: ApplyDirichletBC => & & sField_ApplyDirichletBC1, & & sField_ApplyDirichletBC2 + + ! IO: + ! @IOMethods !! Apply Dirichlet Boundary Condition PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => sField_Import + PROCEDURE, PUBLIC, PASS(obj) :: WriteData_vtk => sField_WriteData_vtk + !! Export data in VTKformat END TYPE ScalarField_ !---------------------------------------------------------------------------- @@ -284,7 +301,7 @@ END FUNCTION sField_Constructor_1 ! date: 16 July 2021 ! summary: This routine Imports the content -INTERFACE +INTERFACE ScalarFieldImport MODULE SUBROUTINE sField_Import(obj, hdf5, group, dom, domains) CLASS(ScalarField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 @@ -292,12 +309,23 @@ MODULE SUBROUTINE sField_Import(obj, hdf5, group, dom, domains) TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE sField_Import -END INTERFACE - -INTERFACE ScalarFieldImport - MODULE PROCEDURE sField_Import END INTERFACE ScalarFieldImport +!---------------------------------------------------------------------------- +! WriteData@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-24 +! summary: Export data in vrkfile + +INTERFACE ScalarFieldWriteData + MODULE SUBROUTINE sField_WriteData_vtk(obj, vtk) + CLASS(ScalarField_), INTENT(INOUT) :: obj + TYPE(VTKFile_), INTENT(INOUT) :: vtk + END SUBROUTINE sField_WriteData_vtk +END INTERFACE ScalarFieldWriteData + !---------------------------------------------------------------------------- ! Set@SetMethods !---------------------------------------------------------------------------- From bc865283711f394f617f2751a91ed5a88c801c3e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 18:24:33 +0900 Subject: [PATCH 035/117] Update ScalarField_Class@IOMethods.F90 - Implementing sField_WriteData_vtk --- .../src/ScalarField_Class@IOMethods.F90 | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 index ee3eadeac..750449d16 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 @@ -18,6 +18,7 @@ SUBMODULE(ScalarField_Class) IOMethods USE BaseMethod USE HDF5File_Method +USE Mesh_Class IMPLICIT NONE CONTAINS @@ -68,4 +69,80 @@ END PROCEDURE sField_Import +!---------------------------------------------------------------------------- +! WriteData +!---------------------------------------------------------------------------- + +MODULE PROCEDURE sField_WriteData_vtk +CHARACTER(*), PARAMETER :: myName = "sField_WriteData_vtk()" +LOGICAL(LGT) :: isOK +TYPE(Domain_), POINTER :: dom +TYPE(Mesh_), POINTER :: meshPtr +INTEGER(I4B) :: imesh, tMesh, nsd +INTEGER(I4B), PARAMETER :: tPhysicalVars = 1 +INTEGER(I4B), ALLOCATABLE :: nptrs(:) +REAL(DFP), ALLOCATABLE :: nodalval(:), xij(:, :) +CHARACTER(1) :: names(tPhysicalVars) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] WriteData()') +#endif + +isOK = obj%isInitiated +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: ScalarNodeField_::obj is not isInitiated.') + RETURN +END IF + +isOK = vtk%isOpen() +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') + RETURN +END IF + +isOK = ASSOCIATED(obj%domain) +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & + & ' not allocated.') + RETURN +END IF + +CALL obj%GetPhysicalNames(names) + +dom => obj%domain +nsd = dom%GetNSD() +tMesh = dom%GetTotalMesh(dim=nsd) + +DO imesh = 1, tMesh + meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) + + CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) + + CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, & + & openTag=.TRUE., content=.TRUE., closeTag=.FALSE.) + + CALL vtk%WriteDataArray(location=String('node'), action=String('open')) + + nptrs = meshPtr%GetNptrs() + + CALL obj%Get(globalNode=nptrs, VALUE=nodalval) + + CALL vtk%WriteDataArray(name=String(names(1)), x=nodalval, & + & numberOfComponents=1) + + CALL vtk%WriteDataArray(location=String('node'), action=String('close')) + + CALL vtk%WritePiece() +END DO + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] WriteData()') +#endif +END PROCEDURE sField_WriteData_vtk + END SUBMODULE IOMethods From 48d79a615158e3f2cd7f6d0c4fa0b2c08da28323 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 22:42:54 +0900 Subject: [PATCH 036/117] Updates in AbstractNodeField - Adding GetFEVariable method - Adding GetTotalPhysicalVars method - Adding GetSpaceCompo method - Adding GetTimeCompo method - Adding WriteData_VTK method --- .../src/AbstractNodeField_Class.F90 | 103 +++++++-- .../AbstractNodeField_Class@GetMethods.F90 | 98 +++++++++ .../src/AbstractNodeField_Class@IOMethods.F90 | 207 ++++++++++++------ 3 files changed, 322 insertions(+), 86 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index abdb92024..2b57f74b5 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -14,7 +14,7 @@ MODULE AbstractNodeField_Class USE GlobalData -USE BaSetype +USE Basetype USE RealVector_Method USE DOF_Method USE AbstractField_Class @@ -37,6 +37,8 @@ MODULE AbstractNodeField_Class PUBLIC :: AbstractNodeFieldGetSingle PUBLIC :: AbstractNodeFieldInitiate PUBLIC :: AbstractNodeFieldSetParam +PUBLIC :: AbstractNodeFieldGetFEVariable + CHARACTER(*), PARAMETER :: modName = "AbstractNodeField_Class" CHARACTER(*), PARAMETER :: myprefix = "AbstractNodeField" @@ -110,8 +112,17 @@ MODULE AbstractNodeField_Class !! Returns the L2 norm PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => anf_GetSingle !! Get single entry + PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => anf_GetFeVariable + !! Get Finite Element variable PROCEDURE, PUBLIC, PASS(obj) :: GetPhysicalNames => anf_GetPhysicalNames !! Get physical names + PROCEDURE, PUBLIC, PASS(obj) :: GetTotalPhysicalVars => & + & anf_GetTotalPhysicalVars + !! Get total physical variables + PROCEDURE, PUBLIC, PASS(obj) :: GetSpaceCompo => anf_GetSpaceCompo + !! Get GetSpaceCompo + PROCEDURE, PUBLIC, PASS(obj) :: GetTimeCompo => anf_GetTimeCompo + !! Get the time components ! Set: ! @SetMethods @@ -264,7 +275,7 @@ END FUNCTION anf_GetPointer ! ! Currently, copyStructure and usePointer is not used -INTERFACE +INTERFACE AbstractNodeFieldInitiate2 MODULE SUBROUTINE anf_Initiate2(obj, obj2, copyFull, copyStructure, & & usePointer) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj @@ -274,10 +285,6 @@ MODULE SUBROUTINE anf_Initiate2(obj, obj2, copyFull, copyStructure, & LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer END SUBROUTINE anf_Initiate2 -END INTERFACE - -INTERFACE AbstractNodeFieldInitiate2 - MODULE PROCEDURE anf_Initiate2 END INTERFACE AbstractNodeFieldInitiate2 !---------------------------------------------------------------------------- @@ -304,14 +311,10 @@ END SUBROUTINE anf_Initiate3 ! date: 21 Oct 2021 ! summary: Deallocates data in [[AbstractNodeField_]] -INTERFACE +INTERFACE AbstractNodeFieldDeallocate MODULE SUBROUTINE anf_Deallocate(obj) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj END SUBROUTINE anf_Deallocate -END INTERFACE - -INTERFACE AbstractNodeFieldDeallocate - MODULE PROCEDURE anf_Deallocate END INTERFACE AbstractNodeFieldDeallocate !---------------------------------------------------------------------------- @@ -337,7 +340,7 @@ END FUNCTION anf_Norm2 ! date: 2023-03-28 ! summary: Set single entry -INTERFACE +INTERFACE AbstractNodeFieldSetSingle MODULE SUBROUTINE anf_SetSingle(obj, indx, VALUE, scale, & & addContribution) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj @@ -346,10 +349,6 @@ MODULE SUBROUTINE anf_SetSingle(obj, indx, VALUE, scale, & REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution END SUBROUTINE anf_SetSingle -END INTERFACE - -INTERFACE AbstractNodeFieldSetSingle - MODULE PROCEDURE anf_SetSingle END INTERFACE AbstractNodeFieldSetSingle !---------------------------------------------------------------------------- @@ -360,18 +359,31 @@ END SUBROUTINE anf_SetSingle ! date: 2023-03-28 ! summary: Set single entry -INTERFACE +INTERFACE AbstractNodeFieldGetSingle MODULE SUBROUTINE anf_GetSingle(obj, indx, VALUE) CLASS(AbstractNodeField_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: indx REAL(DFP), INTENT(OUT) :: VALUE END SUBROUTINE anf_GetSingle -END INTERFACE - -INTERFACE AbstractNodeFieldGetSingle - MODULE PROCEDURE anf_GetSingle END INTERFACE AbstractNodeFieldGetSingle +!---------------------------------------------------------------------------- +! GetFEVariable@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-03-28 +! summary: Set single entry + +INTERFACE AbstractNodeFieldGetFEVariable + MODULE SUBROUTINE anf_GetFeVariable(obj, globalNode, VALUE, ivar) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + TYPE(FEVariable_), INTENT(INOUT) :: VALUE + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END SUBROUTINE anf_GetFeVariable +END INTERFACE AbstractNodeFieldGetFEVariable + !---------------------------------------------------------------------------- ! GetPhysicalNames@GetMethods !---------------------------------------------------------------------------- @@ -387,6 +399,55 @@ MODULE SUBROUTINE anf_GetPhysicalNames(obj, ans) END SUBROUTINE anf_GetPhysicalNames END INTERFACE +!---------------------------------------------------------------------------- +! GetTotalPhysicalVars@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-03 +! summary: Returns the total number of physical variables + +INTERFACE + MODULE FUNCTION anf_GetTotalPhysicalVars(obj) RESULT(ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION anf_GetTotalPhysicalVars +END INTERFACE + +!---------------------------------------------------------------------------- +! GetSpaceCompo@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns space components + +INTERFACE + MODULE FUNCTION anf_GetSpaceCompo(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + !! Total number of physical variables + !! This can be obtained from GetTotalPhysicalVars method + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION anf_GetSpaceCompo +END INTERFACE + +!---------------------------------------------------------------------------- +! GetTimeCompo@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Returns Time components + +INTERFACE + MODULE FUNCTION anf_GetTimeCompo(obj, tPhysicalVars) RESULT(ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: tPhysicalVars + INTEGER(I4B) :: ans(tPhysicalVars) + END FUNCTION anf_GetTimeCompo +END INTERFACE + !---------------------------------------------------------------------------- ! Size !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 index 0af842037..ec277e8ad 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 @@ -20,6 +20,16 @@ IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! GetFEVariable +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetFEVariable +CHARACTER(*), PARAMETER :: myName = "anf_GetFEVariable()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child class.') +END PROCEDURE anf_GetFEVariable + !---------------------------------------------------------------------------- ! GetPhysicalNames !---------------------------------------------------------------------------- @@ -52,6 +62,94 @@ END PROCEDURE anf_GetPhysicalNames +!---------------------------------------------------------------------------- +! GetTotalPhysicalVars +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetTotalPhysicalVars +CHARACTER(*), PARAMETER :: myName = "anf_GetTotalPhysicalVars()" +INTEGER(I4B) :: tnames, aint +LOGICAL(LGT) :: isOK + +ans = 0 +IF (ALLOCATED(obj%dof_names_char)) THEN + tnames = SIZE(obj%dof_names_char) + aint = obj%dof_tPhysicalVars + isOK = tnames .EQ. aint + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The size of names ('//tostring(tnames)// & + & ') is not same as total physical variables = '//tostring(aint)) + RETURN + END IF + ans = aint +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%dof_names_char not'// & + & ' not allocated.') + RETURN +END IF + +END PROCEDURE anf_GetTotalPhysicalVars + +!---------------------------------------------------------------------------- +! GetSpaceCompo +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetSpaceCompo +CHARACTER(*), PARAMETER :: myName = "anf_GetTotalPhysicalVars()" +INTEGER(I4B) :: tnames, aint +LOGICAL(LGT) :: isOK + +ans = 0 +IF (ALLOCATED(obj%dof_spaceCompo)) THEN + tnames = SIZE(obj%dof_spaceCompo) + aint = tPhysicalVars + isOK = tnames .EQ. aint + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The size of spaceCompo ('//tostring(tnames)// & + & ') is not same as total physical variables = '//tostring(aint)) + RETURN + END IF + ans(1:aint) = obj%dof_spaceCompo(1:aint) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%spaceCompo not'// & + & ' not allocated.') + RETURN +END IF +END PROCEDURE anf_GetSpaceCompo + +!---------------------------------------------------------------------------- +! GetTimeCompo +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetTimeCompo +CHARACTER(*), PARAMETER :: myName = "anf_GetTimeCompo()" +INTEGER(I4B) :: tnames, aint +LOGICAL(LGT) :: isOK + +ans = 0 +IF (ALLOCATED(obj%dof_timeCompo)) THEN + tnames = SIZE(obj%dof_timeCompo) + aint = tPhysicalVars + isOK = tnames .EQ. aint + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The size of timeCompo ('//tostring(tnames)// & + & ') is not same as total physical variables = '//tostring(aint)) + RETURN + END IF + ans(1:aint) = obj%dof_timeCompo(1:aint) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%timeCompo not'// & + & ' not allocated.') + RETURN +END IF +END PROCEDURE anf_GetTimeCompo + !---------------------------------------------------------------------------- ! GetPointer !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 index 5fb735876..4aa843da5 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@IOMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(AbstractNodeField_Class) IOMethods USE BaseMethod USE HDF5File_Method +USE Mesh_Class IMPLICIT NONE CONTAINS @@ -112,71 +113,147 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE anf_WriteData_vtk -CHARACTER(*), PARAMETER :: myName = "anf_WriteData()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR]') -! LOGICAL(LGT) :: isOK -! TYPE(Domain_), POINTER :: dom -! TYPE(Mesh_), POINTER :: meshPtr -! INTEGER(I4B) :: imesh, tMesh -! INTEGER(I4B), ALLOCATABLE :: nptrs(:) -! -! #ifdef DEBUG_VER -! CALL e%RaiseInformation(modName//'::'//myName//' - '// & -! & '[START] WriteData()') -! #endif -! -! isOK = obj%isInitiated -! IF (.NOT. isOK) THEN -! CALL e%RaiseInformation(modName//'::'//myName//' - '// & -! & '[INTERNAL ERROR] :: AbstractNodeField_::obj is not isInitiated.') -! RETURN -! END IF -! -! isOK = vtk%isOpen() -! IF (.NOT. isOK) THEN -! CALL e%RaiseInformation(modName//'::'//myName//' - '// & -! & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') -! RETURN -! END IF -! -! isOK = vtk%isWrite() -! IF (isOK) THEN -! CALL e%RaiseInformation(modName//'::'//myName//' - '// & -! & '[INTERNAL ERROR] :: VTKFile_::vtk does not have write access.') -! RETURN -! END IF -! -! isOK = ASSOCIATED(obj%domain) .OR. ALLOCATED(obj%domains) -! IF (.NOT. isOK) THEN -! CALL e%RaiseInformation(modName//'::'//myName//' - '// & -! & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & -! & ' or obj%domains not allocated.') -! RETURN -! END IF -! -! dom => obj%domain -! tMesh = dom%GetTotalMesh() -! -! DO imesh = 1, tMesh -! -! meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) -! CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) -! CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, openTag=.TRUE., & -! & content=.TRUE., closeTag=.FALSE.) -! CALL vtk%WriteDataArray(location=String('node'), action=String('open')) -! nptrs = meshPtr%GetNptrs() -! ! CALL sol%Get(globalNode=nptrs, value=fe) -! ! CALL vtk%WriteDataArray(name=String("sol"), x=fe, numberOfComponents=1) -! CALL vtk%WriteDataArray(location=String('node'), action=String('close')) -! CALL vtk%WritePiece() -! -! END DO -! -! #ifdef DEBUG_VER -! CALL e%RaiseInformation(modName//'::'//myName//' - '// & -! & '[END] WriteData()') -! #endif +CHARACTER(*), PARAMETER :: myName = "anf_WriteData_vtk()" +LOGICAL(LGT) :: isOK, isSingleDomain, isMultiDomain +TYPE(Domain_), POINTER :: dom +TYPE(Mesh_), POINTER :: meshPtr +INTEGER(I4B) :: imesh, tMesh, nsd, tPhysicalVars, tComponents, ivar, & +& tnodes, var_rank, var_vartype, itime +INTEGER(I4B), ALLOCATABLE :: nptrs(:), spaceCompo(:), timeCompo(:) +REAL(DFP), ALLOCATABLE :: r1(:), r2(:, :), r3(:, :, :), xij(:, :) +CHARACTER(1), ALLOCATABLE :: names(:) +TYPE(FEVariable_) :: fevar + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] WriteData()') +#endif + +NULLIFY (dom, meshPtr) + +isOK = obj%isInitiated +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj is not isInitiated.') + RETURN +END IF + +isOK = vtk%isOpen() +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') + RETURN +END IF + +isSingleDomain = ASSOCIATED(obj%domain) +isMultiDomain = ALLOCATED(obj%domains) +isOK = isSingleDomain .OR. isMultiDomain +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & + & ' ot AbstractNodeField_::obj%domains not allocated.') + RETURN +END IF + +tPhysicalVars = obj%GetTotalPhysicalVars() +ALLOCATE (names(tPhysicalVars), spaceCompo(tPhysicalVars), & + & timeCompo(tPhysicalVars)) +CALL obj%GetPhysicalNames(names) +spaceCompo = obj%GetSpaceCompo(tPhysicalVars) +timeCompo = obj%GetTimeCompo(tPhysicalVars) + +IF (isSingleDomain) THEN + dom => obj%domain + nsd = dom%GetNSD() + tMesh = dom%GetTotalMesh(dim=nsd) + + DO imesh = 1, tMesh + meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) + + CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) + + CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, & + & openTag=.TRUE., content=.TRUE., closeTag=.FALSE.) + + CALL vtk%WriteDataArray(location=String('node'), action=String('open')) + + nptrs = meshPtr%GetNptrs() + tnodes = meshPtr%GetTotalNodes() + + DO ivar = 1, tPhysicalVars + CALL obj%GetFEVariable(globalNode=nptrs, VALUE=fevar, ivar=ivar) + + var_rank = .RANK.fevar + var_vartype = .vartype.fevar + + SELECT CASE (var_rank) + CASE (Scalar) + IF (var_vartype .EQ. Space) THEN + r1 = Get(fevar, TypeFEVariableScalar, TypeFEVariableSpace) + CALL vtk%WriteDataArray( & + & name=String(names(ivar)), & + & x=r1, & + & numberOfComponents=spaceCompo(ivar)) + END IF + + IF (var_vartype .EQ. SpaceTime) THEN + r2 = Get(fevar, TypeFEVariableScalar, TypeFEVariableSpaceTime) + DO itime = 1, timeCompo(ivar) + CALL vtk%WriteDataArray( & + & name=String(names(ivar)//"_t"//tostring(itime)), & + & x=r2(itime, :), & + & numberOfComponents=spaceCompo(ivar)) + END DO + END IF + + CASE (Vector) + IF (var_vartype .EQ. Space) THEN + r2 = Get(fevar, TypeFEVariableVector, TypeFEVariableSpace) + CALL vtk%WriteDataArray( & + & name=String(names(ivar)), & + & x=r2, & + & numberOfComponents=spaceCompo(ivar)) + END IF + + IF (var_vartype .EQ. SpaceTime) THEN + r3 = Get(fevar, TypeFEVariableVector, TypeFEVariableSpaceTime) + DO itime = 1, timeCompo(ivar) + CALL vtk%WriteDataArray( & + & name=String(names(ivar)//"_t"//tostring(itime)), & + & x=r3(:, :, itime), & + & numberOfComponents=spaceCompo(ivar)) + END DO + END IF + + CASE DEFAULT + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: No case found for fevar') + END SELECT + + END DO + + CALL vtk%WriteDataArray(location=String('node'), action=String('close')) + + CALL vtk%WritePiece() + END DO + + CALL DEALLOCATE (fevar) + IF (ALLOCATED(nptrs)) DEALLOCATE (nptrs) + IF (ALLOCATED(xij)) DEALLOCATE (xij) + IF (ALLOCATED(r1)) DEALLOCATE (r1) + IF (ALLOCATED(r2)) DEALLOCATE (r2) + IF (ALLOCATED(r3)) DEALLOCATE (r3) + IF (ALLOCATED(names)) DEALLOCATE (names) + IF (ALLOCATED(spaceCompo)) DEALLOCATE (spaceCompo) + IF (ALLOCATED(timeCompo)) DEALLOCATE (timeCompo) + NULLIFY (meshPtr, dom) + +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] WriteData()') +#endif END PROCEDURE anf_WriteData_vtk !---------------------------------------------------------------------------- From 449183d28ad8d9942a6c30d4cdbfe9ce14b83141 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 22:44:57 +0900 Subject: [PATCH 037/117] Update in ScalarField_ - Adding GetFEVariable method - Removing WriteData_VTK - Minor formatting --- .../ScalarField/src/ScalarField_Class.F90 | 53 ++++++------- .../src/ScalarField_Class@GetMethods.F90 | 71 +++++++++-------- .../src/ScalarField_Class@IOMethods.F90 | 76 ------------------- 3 files changed, 67 insertions(+), 133 deletions(-) diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index 81b65e1d8..cc44974cb 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -94,7 +94,7 @@ MODULE ScalarField_Class GENERIC, PUBLIC :: ASSIGNMENT(=) => Set8 !! Set values to a vector - ! GET: + ! Get: ! @GetMethods PROCEDURE, PASS(obj) :: Get1 => sField_Get1 !! Get single entry @@ -110,21 +110,20 @@ MODULE ScalarField_Class !! Get selected values in FEVariable GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, Get5, Get6, Get7 !! Get the entries of scalar field + PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => sField_GetFeVariable + !! Get Finite Element variable ! SET: ! @DirichletBCMethods PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC1 PROCEDURE, PASS(obj) :: sField_ApplyDirichletBC2 - GENERIC, PUBLIC :: ApplyDirichletBC => & - & sField_ApplyDirichletBC1, & + GENERIC, PUBLIC :: ApplyDirichletBC => sField_ApplyDirichletBC1, & & sField_ApplyDirichletBC2 ! IO: ! @IOMethods !! Apply Dirichlet Boundary Condition PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => sField_Import - PROCEDURE, PUBLIC, PASS(obj) :: WriteData_vtk => sField_WriteData_vtk - !! Export data in VTKformat END TYPE ScalarField_ !---------------------------------------------------------------------------- @@ -311,21 +310,6 @@ MODULE SUBROUTINE sField_Import(obj, hdf5, group, dom, domains) END SUBROUTINE sField_Import END INTERFACE ScalarFieldImport -!---------------------------------------------------------------------------- -! WriteData@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-24 -! summary: Export data in vrkfile - -INTERFACE ScalarFieldWriteData - MODULE SUBROUTINE sField_WriteData_vtk(obj, vtk) - CLASS(ScalarField_), INTENT(INOUT) :: obj - TYPE(VTKFile_), INTENT(INOUT) :: vtk - END SUBROUTINE sField_WriteData_vtk -END INTERFACE ScalarFieldWriteData - !---------------------------------------------------------------------------- ! Set@SetMethods !---------------------------------------------------------------------------- @@ -639,7 +623,24 @@ END SUBROUTINE sField_Get7 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! GetFEVariable@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-03-28 +! summary: Set single entry + +INTERFACE ScalarFieldGetFEVariable + MODULE SUBROUTINE sField_GetFeVariable(obj, globalNode, VALUE, ivar) + CLASS(ScalarField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + TYPE(FEVariable_), INTENT(INOUT) :: VALUE + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END SUBROUTINE sField_GetFeVariable +END INTERFACE ScalarFieldGetFEVariable + +!---------------------------------------------------------------------------- +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -647,14 +648,14 @@ END SUBROUTINE sField_Get7 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE sField_applyDirichletBC1(obj, dbc) + MODULE SUBROUTINE sField_ApplyDirichletBC1(obj, dbc) CLASS(ScalarField_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc - END SUBROUTINE sField_applyDirichletBC1 + END SUBROUTINE sField_ApplyDirichletBC1 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -662,10 +663,10 @@ END SUBROUTINE sField_applyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE sField_applyDirichletBC2(obj, dbc) + MODULE SUBROUTINE sField_ApplyDirichletBC2(obj, dbc) CLASS(ScalarField_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) - END SUBROUTINE sField_applyDirichletBC2 + END SUBROUTINE sField_ApplyDirichletBC2 END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 index cc44b094d..1949716ad 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 @@ -21,31 +21,31 @@ CONTAINS !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get1 +MODULE PROCEDURE sField_Get1 IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - VALUE = get( & + VALUE = Get( & & obj=obj%realVec, & & nodenum=1, & & dataType=1.0_DFP) ELSE - VALUE = get( & + VALUE = Get( & & obj=obj%realVec, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode), & + & nodenum=obj%domain%GetLocalNodeNumber(globalNode), & & dataType=1.0_DFP) END IF -END PROCEDURE sField_get1 +END PROCEDURE sField_Get1 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get2 +MODULE PROCEDURE sField_Get2 IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN CALL reallocate(VALUE, obj%tsize) - VALUE = get( & + VALUE = Get( & & obj=obj%realVec, & & nodenum=1, & & dataType=1.0_DFP) @@ -56,61 +56,61 @@ & VALUE=VALUE, & & idof=1) END IF -END PROCEDURE sField_get2 +END PROCEDURE sField_Get2 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get3 -VALUE = get( & +MODULE PROCEDURE sField_Get3 +VALUE = Get( & & obj=obj%realVec, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode), & + & nodenum=obj%domain%GetLocalNodeNumber(globalNode), & & dataType=1.0_DFP) -END PROCEDURE sField_get3 +END PROCEDURE sField_Get3 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get4 +MODULE PROCEDURE sField_Get4 INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%get(globalNode=globalNode, VALUE=VALUE) -END PROCEDURE sField_get4 +CALL obj%Get(globalNode=globalNode, VALUE=VALUE) +END PROCEDURE sField_Get4 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get5 +MODULE PROCEDURE sField_Get5 VALUE = NodalVariable( & - & get( & + & Get( & & obj=obj%realVec, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode), & + & nodenum=obj%domain%GetLocalNodeNumber(globalNode), & & dataType=1.0_DFP), & & TypeFEVariableScalar, & & TypeFEVariableSpace) -END PROCEDURE sField_get5 +END PROCEDURE sField_Get5 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get6 -CALL getValue(obj=obj%realVec, VALUE=VALUE%realVec) -END PROCEDURE sField_get6 +MODULE PROCEDURE sField_Get6 +CALL GetValue(obj=obj%realVec, VALUE=VALUE%realVec) +END PROCEDURE sField_Get6 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE sField_get7 -CHARACTER(*), PARAMETER :: myName = "sField_get7" +MODULE PROCEDURE sField_Get7 +CHARACTER(*), PARAMETER :: myName = "sField_Get7" INTEGER(I4B) :: tsize INTEGER(I4B) :: tsize_value INTEGER(I4B) :: ii @@ -150,6 +150,15 @@ CALL VALUE%SetSingle(VALUE=avar, indx=indx2) END DO -END PROCEDURE sField_get7 +END PROCEDURE sField_Get7 + +!---------------------------------------------------------------------------- +! GetFeVariable +!---------------------------------------------------------------------------- + +MODULE PROCEDURE sField_GetFEVariable +CHARACTER(*), PARAMETER :: myName = "sField_GetFEVariable()" +CALL obj%Get(VALUE=VALUE, globalNode=globalNode) +END PROCEDURE sField_GetFEVariable END SUBMODULE GetMethods diff --git a/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 index 750449d16..75e33056f 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@IOMethods.F90 @@ -69,80 +69,4 @@ END PROCEDURE sField_Import -!---------------------------------------------------------------------------- -! WriteData -!---------------------------------------------------------------------------- - -MODULE PROCEDURE sField_WriteData_vtk -CHARACTER(*), PARAMETER :: myName = "sField_WriteData_vtk()" -LOGICAL(LGT) :: isOK -TYPE(Domain_), POINTER :: dom -TYPE(Mesh_), POINTER :: meshPtr -INTEGER(I4B) :: imesh, tMesh, nsd -INTEGER(I4B), PARAMETER :: tPhysicalVars = 1 -INTEGER(I4B), ALLOCATABLE :: nptrs(:) -REAL(DFP), ALLOCATABLE :: nodalval(:), xij(:, :) -CHARACTER(1) :: names(tPhysicalVars) - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] WriteData()') -#endif - -isOK = obj%isInitiated -IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: ScalarNodeField_::obj is not isInitiated.') - RETURN -END IF - -isOK = vtk%isOpen() -IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: VTKFile_::vtk is not open.') - RETURN -END IF - -isOK = ASSOCIATED(obj%domain) -IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Either AbstractNodeField_::obj%domain, '// & - & ' not allocated.') - RETURN -END IF - -CALL obj%GetPhysicalNames(names) - -dom => obj%domain -nsd = dom%GetNSD() -tMesh = dom%GetTotalMesh(dim=nsd) - -DO imesh = 1, tMesh - meshptr => dom%GetMeshPointer(dim=nsd, entityNum=imesh) - - CALL dom%GetNodeCoord(nodeCoord=xij, dim=nsd, entityNum=imesh) - - CALL meshPtr%ExportToVTK(vtkfile=vtk, nodeCoord=xij, & - & openTag=.TRUE., content=.TRUE., closeTag=.FALSE.) - - CALL vtk%WriteDataArray(location=String('node'), action=String('open')) - - nptrs = meshPtr%GetNptrs() - - CALL obj%Get(globalNode=nptrs, VALUE=nodalval) - - CALL vtk%WriteDataArray(name=String(names(1)), x=nodalval, & - & numberOfComponents=1) - - CALL vtk%WriteDataArray(location=String('node'), action=String('close')) - - CALL vtk%WritePiece() -END DO - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] WriteData()') -#endif -END PROCEDURE sField_WriteData_vtk - END SUBMODULE IOMethods From 5596e16757e11b089efa3a6b5f74e0de734753d1 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 22:48:57 +0900 Subject: [PATCH 038/117] Updates in STScalarField_ - Adding GetFEVariable method --- .../STScalarField/src/STScalarField_Class.F90 | 50 ++++++++++++++++--- ...STScalarField_Class@ConstructorMethods.F90 | 4 +- .../src/STScalarField_Class@GetMethods.F90 | 10 +++- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/modules/STScalarField/src/STScalarField_Class.F90 b/src/modules/STScalarField/src/STScalarField_Class.F90 index 761d985bb..872024dd9 100644 --- a/src/modules/STScalarField/src/STScalarField_Class.F90 +++ b/src/modules/STScalarField/src/STScalarField_Class.F90 @@ -62,15 +62,25 @@ MODULE STScalarField_Class INTEGER(I4B), PUBLIC :: timeCompo = 0_I4B CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & stsField_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => stsField_Initiate1 PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => stsField_Initiate2 + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => stsField_Deallocate + FINAL :: stsField_Final + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => stsField_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => stsField_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => stsField_Export - PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => stsField_Deallocate - FINAL :: stsField_Final + + ! SET: + ! @SetMethods PROCEDURE, PASS(obj) :: Set1 => stsField_Set1 !! Set single entry PROCEDURE, PASS(obj) :: Set2 => stsField_Set2 @@ -102,6 +112,9 @@ MODULE STScalarField_Class PROCEDURE, PASS(obj) :: Set15 => stsField_Set15 GENERIC, PUBLIC :: Set => Set1, Set2, Set3, Set4, Set5, Set6, & & Set7, Set8, Set9, Set10, Set11, Set12, Set13, Set14 + + ! GET: + ! @GetMethods PROCEDURE, PASS(obj) :: Get1 => stsField_Get1 PROCEDURE, PASS(obj) :: Get2 => stsField_Get2 PROCEDURE, PASS(obj) :: Get3 => stsField_Get3 @@ -114,14 +127,19 @@ MODULE STScalarField_Class PROCEDURE, PASS(obj) :: Get10 => stsField_Get10 GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, & & Get5, Get6, Get7, Get8, Get9 + PROCEDURE, PASS(obj) :: GetPointerOfComponent => & + & stsField_GetPointerOfComponent + PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => stsField_GetFeVariable + !! Get Finite Element variable + + ! SET: + ! @DirichletBCMethods PROCEDURE, PASS(obj) :: stsField_applyDirichletBC1 PROCEDURE, PASS(obj) :: stsField_applyDirichletBC2 - GENERIC, PUBLIC :: applyDirichletBC => & - & stsField_applyDirichletBC1, & + GENERIC, PUBLIC :: applyDirichletBC => stsField_applyDirichletBC1, & & stsField_applyDirichletBC2 - !! Get the entries of STScalar field - PROCEDURE, PASS(obj) :: GetPointerOfComponent => & - & stsField_GetPointerOfComponent + !! Get the entries of STScalar field + END TYPE STScalarField_ !---------------------------------------------------------------------------- @@ -1022,6 +1040,24 @@ MODULE SUBROUTINE stsField_Get10(obj, ivar, idof, VALUE, ivar_value, idof_value) END SUBROUTINE stsField_Get10 END INTERFACE +!---------------------------------------------------------------------------- +! GetFEVariable@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-03-28 +! summary: Set single entry + +INTERFACE STScalarFieldGetFEVariable + MODULE SUBROUTINE stsField_GetFeVariable(obj, globalNode, VALUE, ivar) + CLASS(STScalarField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + TYPE(FEVariable_), INTENT(INOUT) :: VALUE + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + !! This argument is not used + END SUBROUTINE stsField_GetFeVariable +END INTERFACE STScalarFieldGetFEVariable + !---------------------------------------------------------------------------- ! applyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index a14296b7a..9d813d1d8 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -71,7 +71,7 @@ MODULE PROCEDURE stsField_Initiate1 CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1()" TYPE(String) :: astr -INTEGER(I4B) :: nsd, tdof, ierr, timeCompo, tNodes +INTEGER(I4B) :: nsd, tdof, ierr, timeCompo, tNodes TYPE(ParameterList_), POINTER :: sublist ! main @@ -93,7 +93,7 @@ CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", VALUE=timeCompo) -tNodes = dom%GetTotalNodes() +tNodes = dom%GetTotalNodes() tdof = tNodes * timeCompo CALL AbstractNodeFieldSetParam(obj=obj, & diff --git a/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 index ce6b7e306..b4ce5df99 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 @@ -273,7 +273,15 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE stsField_GetTimeCompo - ans = obj%timeCompo +ans = obj%timeCompo END PROCEDURE stsField_GetTimeCompo +!---------------------------------------------------------------------------- +! GetFEVariable +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stsField_GetFEVariable +CALL obj%Get(globalNode=globalNode, VALUE=VALUE) +END PROCEDURE stsField_GetFEVariable + END SUBMODULE GetMethods From 4bc0531c9bdf5b4f5ef3655cd02cdbf95266b829 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 23:19:23 +0900 Subject: [PATCH 039/117] Update STScalarField_ - Removing sField_Initiate_old method - Removing bug from stsField_Initiate1 method --- .../ScalarField/src/ScalarField_Class.F90 | 23 ----- ...STScalarField_Class@ConstructorMethods.F90 | 15 ++-- .../ScalarField_Class@ConstructorMethods.F90 | 84 +------------------ 3 files changed, 11 insertions(+), 111 deletions(-) diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index cc44974cb..d6cdf566d 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -201,29 +201,6 @@ END SUBROUTINE sField_CheckEssentialParam ! scalar field. There are essential and optional information. ! Essential information are described below. -INTERFACE - MODULE SUBROUTINE sField_Initiate_old(obj, param, dom) - CLASS(ScalarField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE sField_Initiate_old -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@Constructor -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 25 June 2021 -! summary: This subroutine initiates the ScalarField_ object -! -!# Introduction -! -! This routine initiate the [[ScalarField_]] object. -! `param` contains the information of parameters required to initiate the -! scalar field. There are essential and optional information. -! Essential information are described below. - INTERFACE ScalarFieldInitiate1 MODULE SUBROUTINE sField_Initiate1(obj, param, dom) CLASS(ScalarField_), INTENT(INOUT) :: obj diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index 5fce90235..f1ce88e48 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -46,11 +46,13 @@ IF (ierr .NE. 0_I4B) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + RETURN END IF IF (.NOT. ASSOCIATED(sublist)) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') + RETURN END IF CALL Set( & @@ -82,8 +84,9 @@ MODULE PROCEDURE stsField_Initiate1 CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1()" +CHARACTER(1) :: names(1) TYPE(String) :: astr -INTEGER(I4B) :: nsd, tdof, ierr, timeCompo, tNodes +INTEGER(I4B) :: nsd, tdof, ierr, tNodes TYPE(ParameterList_), POINTER :: sublist ! main @@ -104,17 +107,19 @@ CALL obj%DEALLOCATE() CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) -CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", VALUE=timeCompo) +CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", & + & VALUE=obj%timeCompo) tNodes = dom%GetTotalNodes() -tdof = tNodes * timeCompo +tdof = tNodes * obj%timeCompo +names(1) (:) = astr%slice(1, 1) CALL AbstractNodeFieldSetParam(obj=obj, & & dof_tPhysicalVars=1_I4B, & & dof_storageFMT=NODES_FMT, & & dof_spaceCompo=[1_I4B], & - & dof_timeCompo=[timeCompo], & + & dof_timeCompo=[obj%timeCompo], & & dof_tNodes=[tNodes], & - & dof_names_char=[astr%slice(1, 1)], & + & dof_names_char=names, & & tSize=tdof) nsd = dom%GetNSD() diff --git a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 index a636fea46..31ab4ef00 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 @@ -51,10 +51,10 @@ MODULE PROCEDURE sField_Initiate1 CHARACTER(*), PARAMETER :: myName = "sField_Initiate1()" +CHARACTER(1) :: names(1) TYPE(String) :: astr INTEGER(I4B) :: nsd, tdof, ierr, tNodes TYPE(ParameterList_), POINTER :: sublist -CHARACTER(1) :: names(1) ! main sublist => NULL() @@ -99,88 +99,6 @@ sublist => NULL() END PROCEDURE sField_Initiate1 -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE sField_Initiate_old -! CHARACTER(*), PARAMETER :: myName = "sField_Initiate1" -! INTEGER(I4B) :: ierr, storageFMT -! INTEGER(I4B) :: tNodes(1), spaceCompo(1), timeCompo(1) -! CHARACTER(:), ALLOCATABLE :: char_var -! CHARACTER(1) :: names_char(1) -! -! ! main program -! CALL obj%DEALLOCATE() -! CALL obj%CheckEssentialParam(param) -! -! ! engine -! ALLOCATE (CHARACTER( & -! & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) -! ierr = param%Get(key=myprefix//"/engine", VALUE=char_var) -! obj%engine = char_var -! DEALLOCATE (char_var) -! -! ! name -! ALLOCATE (CHARACTER( & -! & param%DataSizeInBytes(key=myprefix//"/name")) :: char_var) -! ierr = param%Get(key=myprefix//"/name", VALUE=char_var) -! obj%name = char_var -! names_char(1) (1:1) = char_var(1:1) -! DEALLOCATE (char_var) -! -! ! fieldType -! IF (param%isPresent(key=myprefix//"/fieldType")) THEN -! ierr = param%Get(key=myprefix//"/fieldType", VALUE=obj%fieldType) -! ELSE -! obj%fieldType = FIELD_TYPE_NORMAL -! END IF -! -! ! comm -! ierr = param%Get(key=myprefix//"/comm", VALUE=obj%comm) -! ierr = param%Get(key=myprefix//"/global_n", VALUE=obj%global_n) -! ierr = param%Get(key=myprefix//"/local_n", VALUE=obj%local_n) -! -! spaceCompo = [1] -! timeCompo = [1] -! storageFMT = FMT_NODES -! obj%domain => dom -! IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN -! tNodes = 1 -! obj%tSize = obj%domain%GetTotalNodes() -! IF (obj%local_n .EQ. 0) THEN -! obj%local_n = tNodes(1) -! END IF -! IF (obj%global_n .EQ. 0) THEN -! obj%global_n = tNodes(1) -! END IF -! ELSE -! tNodes = obj%domain%GetTotalNodes() -! obj%tSize = tNodes(1) -! IF (obj%local_n .EQ. 0) THEN -! obj%local_n = obj%tSize -! END IF -! IF (obj%global_n .EQ. 0) THEN -! obj%global_n = obj%tSize -! END IF -! END IF -! -! CALL Initiate( & -! & obj=obj%dof, & -! & tNodes=tNodes, & -! & names=names_char, & -! & spaceCompo=spaceCompo, & -! & timeCompo=timeCompo, & -! & storageFMT=storageFMT) -! -! CALL Initiate(obj%realVec, obj%dof) -! -! obj%isInitiated = .TRUE. -! -! IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -! -END PROCEDURE sField_Initiate_old - !---------------------------------------------------------------------------- ! Final !---------------------------------------------------------------------------- From bab720826f79d7ae72d23472f828a7b05af8378d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 23:45:03 +0900 Subject: [PATCH 040/117] Update STScalarField Removing stsField_Initiate1_old method --- .../STScalarField/src/STScalarField_Class.F90 | 25 ------ ...STScalarField_Class@ConstructorMethods.F90 | 88 ------------------- 2 files changed, 113 deletions(-) diff --git a/src/modules/STScalarField/src/STScalarField_Class.F90 b/src/modules/STScalarField/src/STScalarField_Class.F90 index 872024dd9..9744f4f80 100644 --- a/src/modules/STScalarField/src/STScalarField_Class.F90 +++ b/src/modules/STScalarField/src/STScalarField_Class.F90 @@ -218,31 +218,6 @@ END SUBROUTINE stsField_checkEssentialParam ! - `timeCompo` is the total degree of freedom or components ! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL -INTERFACE - MODULE SUBROUTINE stsField_Initiate1_old(obj, param, dom) - CLASS(STScalarField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE stsField_Initiate1_old -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@Constructor -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 25 June 2021 -! summary: This subroutine initiates the STScalarField_ object -! -!# Introduction -! This routine initiate the STScalar field object. -! `param` contains the information of parameters required to initiate the -! STScalar. There are essential and optional information. -! Essential information are described below. -! - `name` character defining the name of STScalar field -! - `timeCompo` is the total degree of freedom or components -! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL - INTERFACE STScalarFieldInitiate1 MODULE SUBROUTINE stsField_Initiate1(obj, param, dom) CLASS(STScalarField_), INTENT(INOUT) :: obj diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index f1ce88e48..115c4bead 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -134,94 +134,6 @@ sublist => NULL() END PROCEDURE stsField_Initiate1 -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE stsField_Initiate1_old -CHARACTER(*), PARAMETER :: myName = "stsField_Initiate1_old" -INTEGER(I4B) :: ierr, storageFMT, tNodes(1), spaceCompo(1), & - & timeCompo(1) -CHARACTER(:), ALLOCATABLE :: char_var -CHARACTER(1) :: names_char(1) - -! main program -IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'STScalarField_::obj is already initiated') -END IF - -CALL obj%CheckEssentialParam(param) - -! engine -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) -ierr = param%Get(key=myprefix//"/engine", VALUE=char_var) -obj%engine = char_var -DEALLOCATE (char_var) - -! name -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/name")) :: char_var) -ierr = param%Get(key=myprefix//"/name", VALUE=char_var) -obj%name = char_var -names_char(1) (1:1) = char_var(1:1) -DEALLOCATE (char_var) - -! fieldType -IF (param%isPresent(key=myprefix//"/fieldType")) THEN - ierr = param%Get(key=myprefix//"/fieldType", VALUE=obj%fieldType) -ELSE - obj%fieldType = FIELD_TYPE_NORMAL -END IF - -! comm -ierr = param%Get(key=myprefix//"/comm", VALUE=obj%comm) -ierr = param%Get(key=myprefix//"/global_n", VALUE=obj%global_n) -ierr = param%Get(key=myprefix//"/local_n", VALUE=obj%local_n) - -! timeCompo -ierr = param%Get(key=myprefix//"/timeCompo", VALUE=obj%timeCompo) - -timeCompo = obj%timeCompo -spaceCompo = 1 -storageFMT = FMT_NODES -obj%domain => dom -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - tNodes = 1 - obj%tSize = obj%domain%GetTotalNodes() * obj%timeCompo - IF (obj%local_n .EQ. 0) THEN - obj%local_n = tNodes(1) * obj%timeCompo - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = tNodes(1) * obj%timeCompo - END IF -ELSE - tNodes = obj%domain%GetTotalNodes() - obj%tSize = tNodes(1) * obj%timeCompo - IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize - END IF -END IF - -CALL Initiate( & - & obj=obj%dof, & - & tNodes=tNodes, & - & names=names_char, & - & spaceCompo=spaceCompo, & - & timeCompo=timeCompo, & - & storageFMT=storageFMT) - -CALL Initiate(obj%realVec, obj%dof) - -obj%isInitiated = .TRUE. - -IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE stsField_Initiate1_old - !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- From cea8b0b1addd65f58f8a40440779ab4b09269cde Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sat, 25 Nov 2023 23:54:11 +0900 Subject: [PATCH 041/117] Update STScalarField_Class.F90 - Minor formatting in STScalarField_Class --- .../STScalarField/src/STScalarField_Class.F90 | 77 ++++++------------- 1 file changed, 25 insertions(+), 52 deletions(-) diff --git a/src/modules/STScalarField/src/STScalarField_Class.F90 b/src/modules/STScalarField/src/STScalarField_Class.F90 index 9744f4f80..1a4ead95e 100644 --- a/src/modules/STScalarField/src/STScalarField_Class.F90 +++ b/src/modules/STScalarField/src/STScalarField_Class.F90 @@ -37,7 +37,7 @@ MODULE STScalarField_Class PUBLIC :: STScalarField_ PUBLIC :: STScalarFieldPointer_ PUBLIC :: SetSTScalarFieldParam -PUBLIC :: stsField_checkEssentialParam +PUBLIC :: stsField_CheckEssentialParam PUBLIC :: STScalarFieldInitiate1 PUBLIC :: STScalarFieldInitiate2 PUBLIC :: STScalarFieldDeallocate @@ -134,10 +134,10 @@ MODULE STScalarField_Class ! SET: ! @DirichletBCMethods - PROCEDURE, PASS(obj) :: stsField_applyDirichletBC1 - PROCEDURE, PASS(obj) :: stsField_applyDirichletBC2 - GENERIC, PUBLIC :: applyDirichletBC => stsField_applyDirichletBC1, & - & stsField_applyDirichletBC2 + PROCEDURE, PASS(obj) :: stsField_ApplyDirichletBC1 + PROCEDURE, PASS(obj) :: stsField_ApplyDirichletBC2 + GENERIC, PUBLIC :: ApplyDirichletBC => stsField_ApplyDirichletBC1, & + & stsField_ApplyDirichletBC2 !! Get the entries of STScalar field END TYPE STScalarField_ @@ -180,25 +180,25 @@ END SUBROUTINE SetSTScalarFieldParam END INTERFACE !---------------------------------------------------------------------------- -! checkEssentialParam@Constructor +! CheckEssentialParam@Constructor !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine check the essential parameters in param. +! summary: This routine Check the essential parameters in param. ! !# Introduction -! This routine check the essential parameters required to the initiate the +! This routine Check the essential parameters required to the initiate the ! [[STScalarField_]] data type. We need following parameters ! ! - CHARACTER( * ) :: name ! - INTEGER( I4B ) :: tdof INTERFACE - MODULE SUBROUTINE stsField_checkEssentialParam(obj, param) + MODULE SUBROUTINE stsField_CheckEssentialParam(obj, param) CLASS(STScalarField_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE stsField_checkEssentialParam + END SUBROUTINE stsField_CheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- @@ -234,7 +234,7 @@ END SUBROUTINE stsField_Initiate1 ! date: 2023-03-29 ! summary: Initiate2 -INTERFACE +INTERFACE STScalarFieldInitiate2 MODULE SUBROUTINE stsField_Initiate2(obj, obj2, copyFull, copyStructure, & & usePointer) CLASS(STScalarField_), INTENT(INOUT) :: obj @@ -244,10 +244,6 @@ MODULE SUBROUTINE stsField_Initiate2(obj, obj2, copyFull, copyStructure, & LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer END SUBROUTINE stsField_Initiate2 -END INTERFACE - -INTERFACE STScalarFieldInitiate2 - MODULE PROCEDURE stsField_Initiate2 END INTERFACE STScalarFieldInitiate2 !---------------------------------------------------------------------------- @@ -258,14 +254,10 @@ END SUBROUTINE stsField_Initiate2 ! date: 25 June 2021 ! summary: This routine deallocates the data stored inside the STScalarField_ obj -INTERFACE +INTERFACE STScalarFieldDeallocate MODULE SUBROUTINE stsField_Deallocate(obj) CLASS(STScalarField_), INTENT(INOUT) :: obj END SUBROUTINE stsField_Deallocate -END INTERFACE - -INTERFACE STScalarFieldDeallocate - MODULE PROCEDURE stsField_Deallocate END INTERFACE STScalarFieldDeallocate !---------------------------------------------------------------------------- @@ -286,16 +278,12 @@ END SUBROUTINE stsField_Final ! date: 25 June 2021 ! summary: This function returns an instance of [[STScalarField_]] -INTERFACE +INTERFACE STScalarField MODULE FUNCTION stsField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom TYPE(STScalarField_) :: ans END FUNCTION stsField_Constructor1 -END INTERFACE - -INTERFACE STScalarField - MODULE PROCEDURE stsField_Constructor1 END INTERFACE STScalarField !---------------------------------------------------------------------------- @@ -306,16 +294,12 @@ END FUNCTION stsField_Constructor1 ! date: 25 June 2021 ! summary: This function returns an instance of [[STScalarField_]] -INTERFACE +INTERFACE STScalarField_Pointer MODULE FUNCTION stsField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom CLASS(STScalarField_), POINTER :: ans END FUNCTION stsField_Constructor_1 -END INTERFACE - -INTERFACE STScalarField_Pointer - MODULE PROCEDURE stsField_Constructor_1 END INTERFACE STScalarField_Pointer !---------------------------------------------------------------------------- @@ -326,16 +310,12 @@ END FUNCTION stsField_Constructor_1 ! date: 26 June 2021 ! summary: Display the content of [[STScalarField_]] -INTERFACE +INTERFACE STScalarFieldDisplay MODULE SUBROUTINE stsField_Display(obj, msg, unitNo) CLASS(STScalarField_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo END SUBROUTINE stsField_Display -END INTERFACE - -INTERFACE STScalarFieldDisplay - MODULE PROCEDURE stsField_Display END INTERFACE STScalarFieldDisplay !---------------------------------------------------------------------------- @@ -346,7 +326,7 @@ END SUBROUTINE stsField_Display ! date: 16 July 2021 ! summary: This routine Imports the content -INTERFACE +INTERFACE STScalarFieldImport MODULE SUBROUTINE stsField_Import(obj, hdf5, group, dom, domains) CLASS(STScalarField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 @@ -354,10 +334,6 @@ MODULE SUBROUTINE stsField_Import(obj, hdf5, group, dom, domains) TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE stsField_Import -END INTERFACE - -INTERFACE STScalarFieldImport - MODULE PROCEDURE stsField_Import END INTERFACE STScalarFieldImport !---------------------------------------------------------------------------- @@ -368,16 +344,12 @@ END SUBROUTINE stsField_Import ! date: 16 July 2021 ! summary: This routine Exports the content -INTERFACE +INTERFACE STScalarFieldExport MODULE SUBROUTINE stsField_Export(obj, hdf5, group) CLASS(STScalarField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE stsField_Export -END INTERFACE - -INTERFACE STScalarFieldExport - MODULE PROCEDURE stsField_Export END INTERFACE STScalarFieldExport !---------------------------------------------------------------------------- @@ -1005,7 +977,8 @@ END SUBROUTINE stsField_Get9 ! summary: Get values INTERFACE -MODULE SUBROUTINE stsField_Get10(obj, ivar, idof, VALUE, ivar_value, idof_value) + MODULE SUBROUTINE stsField_Get10(obj, ivar, idof, VALUE, ivar_value, & + & idof_value) CLASS(STScalarField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar @@ -1034,7 +1007,7 @@ END SUBROUTINE stsField_GetFeVariable END INTERFACE STScalarFieldGetFEVariable !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -1042,14 +1015,14 @@ END SUBROUTINE stsField_GetFeVariable ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE stsField_applyDirichletBC1(obj, dbc) + MODULE SUBROUTINE stsField_ApplyDirichletBC1(obj, dbc) CLASS(STScalarField_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc - END SUBROUTINE stsField_applyDirichletBC1 + END SUBROUTINE stsField_ApplyDirichletBC1 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -1057,10 +1030,10 @@ END SUBROUTINE stsField_applyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE stsField_applyDirichletBC2(obj, dbc) + MODULE SUBROUTINE stsField_ApplyDirichletBC2(obj, dbc) CLASS(STScalarField_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) - END SUBROUTINE stsField_applyDirichletBC2 + END SUBROUTINE stsField_ApplyDirichletBC2 END INTERFACE !---------------------------------------------------------------------------- From 267304f883b0a9463e748b39f34dc97c3c07d1c1 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 00:03:02 +0900 Subject: [PATCH 042/117] Updates in STScalarFieldLis - Minor updating related to formatting --- .../src/STScalarFieldLis_Class.F90 | 52 +++++++++++-------- ...calarFieldLis_Class@ConstructorMethods.F90 | 10 +--- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 b/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 index 27660017d..863801182 100644 --- a/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 +++ b/src/modules/STScalarFieldLis/src/STScalarFieldLis_Class.F90 @@ -38,6 +38,8 @@ MODULE STScalarFieldLis_Class PUBLIC :: STScalarFieldLisPointer_ PUBLIC :: STScalarFieldLis PUBLIC :: STScalarFieldLis_Pointer +PUBLIC :: TypeSTScalarField +PUBLIC :: STScalarFieldLisDeallocate !---------------------------------------------------------------------------- ! STScalarFieldLis_ @@ -53,19 +55,21 @@ MODULE STScalarFieldLis_Class #ifdef USE_LIS CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => stsField_Initiate1 PROCEDURE, PUBLIC, PASS(obj) :: Display => stsField_Display - PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => stsField_Import - PROCEDURE, PUBLIC, PASS(obj) :: Export => stsField_Export PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => stsField_Deallocate FINAL :: stsField_Final - PROCEDURE, PUBLIC, PASS(obj) :: Norm2 => stsField_Norm2 - PROCEDURE, PUBLIC, PASS(obj) :: Norm1 => stsField_Norm1 - PROCEDURE, PUBLIC, PASS(obj) :: Normi => stsField_Normi - PROCEDURE, PUBLIC, PASS(obj) :: Size => stsField_Size - ! + + ! IO: + ! @IOMethods + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => stsField_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => stsField_Export + + ! SET: ! @SetMethods - ! PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => stsField_SetSingle PROCEDURE, PASS(obj) :: SetAll => stsField_SetAll PROCEDURE, PASS(obj) :: SetMultiple => stsField_SetMultiple @@ -97,9 +101,16 @@ MODULE STScalarFieldLis_Class !! Set values using FEVariable PROCEDURE, PASS(obj) :: Set14 => stsField_Set14 !! Set values using FEVariable - ! + + ! GET: + ! @BlasMethods + PROCEDURE, PUBLIC, PASS(obj) :: Norm2 => stsField_Norm2 + PROCEDURE, PUBLIC, PASS(obj) :: Norm1 => stsField_Norm1 + PROCEDURE, PUBLIC, PASS(obj) :: Normi => stsField_Normi + + ! GET: ! @GetMethods - ! + PROCEDURE, PUBLIC, PASS(obj) :: Size => stsField_Size PROCEDURE, PUBLIC, PASS(obj) :: GetSingle => stsField_GetSingle PROCEDURE, PASS(obj) :: Get1 => stsField_Get1 PROCEDURE, PASS(obj) :: Get2 => stsField_Get2 @@ -121,10 +132,10 @@ MODULE STScalarFieldLis_Class END TYPE STScalarFieldLis_ !---------------------------------------------------------------------------- -! +! !---------------------------------------------------------------------------- -TYPE(STScalarFieldLis_), PARAMETER, PUBLIC :: TypeSTScalarField = & +TYPE(STScalarFieldLis_), PARAMETER :: TypeSTScalarField = & & STScalarFieldLis_(domains=NULL()) !---------------------------------------------------------------------------- @@ -135,7 +146,6 @@ MODULE STScalarFieldLis_Class CLASS(STScalarFieldLis_), POINTER :: ptr => NULL() END TYPE STScalarFieldLisPointer_ - !---------------------------------------------------------------------------- ! STScalar@Constructor !---------------------------------------------------------------------------- @@ -147,7 +157,7 @@ MODULE STScalarFieldLis_Class INTERFACE STScalarFieldLis MODULE FUNCTION stsField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom TYPE(STScalarFieldLis_) :: ans END FUNCTION stsField_Constructor1 END INTERFACE STScalarFieldLis @@ -163,7 +173,7 @@ END FUNCTION stsField_Constructor1 INTERFACE STScalarFieldLis_Pointer MODULE FUNCTION stsField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom CLASS(STScalarFieldLis_), POINTER :: ans END FUNCTION stsField_Constructor_1 END INTERFACE STScalarFieldLis_Pointer @@ -201,7 +211,7 @@ END SUBROUTINE stsField_Final MODULE SUBROUTINE stsField_Initiate1(obj, param, dom) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom END SUBROUTINE stsField_Initiate1 END INTERFACE @@ -219,8 +229,6 @@ MODULE SUBROUTINE stsField_Deallocate(obj) END SUBROUTINE stsField_Deallocate END INTERFACE STScalarFieldLisDeallocate -PUBLIC :: STScalarFieldLisDeallocate - !---------------------------------------------------------------------------- ! Display@IO !---------------------------------------------------------------------------- @@ -250,8 +258,8 @@ MODULE SUBROUTINE stsField_Import(obj, hdf5, group, dom, domains) CLASS(STScalarFieldLis_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE stsField_Import END INTERFACE @@ -416,7 +424,7 @@ END SUBROUTINE stsField_Set1 INTERFACE MODULE SUBROUTINE stsField_Set2(obj, VALUE, scale, addContribution) - CLASS(STScalarFieldLis_), TARGet, INTENT(INOUT) :: obj + CLASS(STScalarFieldLis_), TARGET, INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution @@ -974,7 +982,7 @@ END FUNCTION stsField_GetPointerOfComponent INTERFACE MODULE FUNCTION stsField_GetPointer(obj) RESULT(ans) - CLASS(STScalarFieldLis_), TARGet, INTENT(IN) :: obj + CLASS(STScalarFieldLis_), TARGET, INTENT(IN) :: obj REAL(DFP), POINTER :: ans(:) END FUNCTION stsField_GetPointer END INTERFACE diff --git a/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@ConstructorMethods.F90 b/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@ConstructorMethods.F90 index 1b6ed6ba5..3631abc3b 100644 --- a/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarFieldLis/src/STScalarFieldLis_Class@ConstructorMethods.F90 @@ -61,16 +61,10 @@ CALL lis_vector_create(obj%comm, obj%lis_ptr, ierr) CALL CHKERR(ierr) -CALL lis_vector_set_size(obj%lis_ptr, obj%local_n, & -& obj%global_n, ierr) +CALL lis_vector_set_size(obj%lis_ptr, obj%local_n, obj%global_n, ierr) CALL CHKERR(ierr) -CALL lis_vector_get_range( & -& obj%lis_ptr, & -& obj%is, & -& obj%ie, & -& ierr & -& ) +CALL lis_vector_get_range(obj%lis_ptr, obj%is, obj%ie, ierr) CALL CHKERR(ierr) END PROCEDURE stsField_Initiate1 From 5d7e0cc9142a53332cdc10789517e0add3475b36 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 00:36:16 +0900 Subject: [PATCH 043/117] Updates in VectorField Fixes issue #193 for VectorField and VectorFieldLis --- .../ScalarField/src/ScalarField_Class.F90 | 17 +-- .../VectorField/src/VectorField_Class.F90 | 73 ++++++----- .../VectorField_Class@ConstructorMethods.F90 | 114 ++++-------------- .../src/VectorField_Class@GetMethods.F90 | 114 ++++++++++-------- 4 files changed, 129 insertions(+), 189 deletions(-) diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index d6cdf566d..944108f38 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -44,6 +44,7 @@ MODULE ScalarField_Class PUBLIC :: ScalarField_Pointer PUBLIC :: ScalarFieldImport PUBLIC :: ScalarFieldDeallocate +PUBLIC :: TypeScalarField !---------------------------------------------------------------------------- ! ScalarField_ @@ -130,8 +131,8 @@ MODULE ScalarField_Class ! !---------------------------------------------------------------------------- -TYPE(ScalarField_), PARAMETER, PUBLIC :: & - & TypeScalarField = ScalarField_(domains=NULL()) +TYPE(ScalarField_), PARAMETER :: TypeScalarField = & + & ScalarField_(domains=NULL()) !---------------------------------------------------------------------------- ! ScalarFieldPointer_ @@ -237,16 +238,12 @@ END SUBROUTINE sField_Deallocate ! date: 25 June 2021 ! summary: This function returns an instance of [[ScalarField_]] -INTERFACE +INTERFACE ScalarField MODULE FUNCTION sField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom TYPE(ScalarField_) :: ans END FUNCTION sField_Constructor1 -END INTERFACE - -INTERFACE ScalarField - MODULE PROCEDURE sField_Constructor1 END INTERFACE ScalarField !---------------------------------------------------------------------------- @@ -257,16 +254,12 @@ END FUNCTION sField_Constructor1 ! date: 25 June 2021 ! summary: This function returns an instance of [[ScalarField_]] -INTERFACE +INTERFACE ScalarField_Pointer MODULE FUNCTION sField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom CLASS(ScalarField_), POINTER :: ans END FUNCTION sField_Constructor_1 -END INTERFACE - -INTERFACE ScalarField_Pointer - MODULE PROCEDURE sField_Constructor_1 END INTERFACE ScalarField_Pointer !---------------------------------------------------------------------------- diff --git a/src/modules/VectorField/src/VectorField_Class.F90 b/src/modules/VectorField/src/VectorField_Class.F90 index b1ac732ee..5674c634f 100644 --- a/src/modules/VectorField/src/VectorField_Class.F90 +++ b/src/modules/VectorField/src/VectorField_Class.F90 @@ -44,6 +44,7 @@ MODULE VectorField_Class PUBLIC :: VectorField_Pointer PUBLIC :: VectorFieldDisplay PUBLIC :: VectorFieldExport +PUBLIC :: TypeVectorField !---------------------------------------------------------------------------- ! VectorField_ @@ -53,24 +54,33 @@ MODULE VectorField_Class ! date: 25 June 2021 ! summary: Vector field ! -!{!pages/docs-api/VectorField/VectorField_.md} +!{!pages/docs-api/VectorField/VectorField_.md!} TYPE, EXTENDS(AbstractNodeField_) :: VectorField_ INTEGER(I4B) :: spaceCompo = 0_I4B CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & & vField_checkEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => vField_Initiate1 PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => vField_Initiate2 PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => vField_Deallocate + FINAL :: vField_Final + PROCEDURE, PUBLIC, PASS(obj) :: GetPointerOfComponent => & & vField_GetPointerOfComponent + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => vField_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => vField_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => vField_Export - FINAL :: vField_Final - !! SetMethods + + ! SET: + ! @SetMethods PROCEDURE, PASS(obj) :: Set1 => vField_Set1 !! Set single entry PROCEDURE, PASS(obj) :: Set2 => vField_Set2 @@ -104,6 +114,8 @@ MODULE VectorField_Class & Set7, Set8, Set9, Set10, Set11, Set12, & & Set13, Set14, Set15 + ! GET: + ! @GetMethods PROCEDURE, PASS(obj) :: Get1 => vField_Get1 !! returns the single entry PROCEDURE, PASS(obj) :: Get2 => vField_Get2 @@ -121,14 +133,21 @@ MODULE VectorField_Class GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, & & Get5, Get6, Get7, Get8, Get9, Get10, Get11 !! Get the entries of Vector field + PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => vField_GetFeVariable + + ! SET: + ! @DirichletBCMethods PROCEDURE, PASS(obj) :: vField_ApplyDirichletBC1 PROCEDURE, PASS(obj) :: vField_ApplyDirichletBC2 - GENERIC, PUBLIC :: ApplyDirichletBC => & - & vField_ApplyDirichletBC1, & + GENERIC, PUBLIC :: ApplyDirichletBC => vField_ApplyDirichletBC1, & & vField_ApplyDirichletBC2 END TYPE VectorField_ -TYPE(VectorField_), PARAMETER, PUBLIC :: TypeVectorField = & +!---------------------------------------------------------------------------- +! TypeVectorField +!---------------------------------------------------------------------------- + +TYPE(VectorField_), PARAMETER :: TypeVectorField = & & VectorField_(domains=NULL()) !---------------------------------------------------------------------------- @@ -208,31 +227,6 @@ MODULE SUBROUTINE vField_Initiate1(obj, param, dom) END SUBROUTINE vField_Initiate1 END INTERFACE VectorFieldInitiate1 -!---------------------------------------------------------------------------- -! Initiate@Constructor -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 25 June 2021 -! summary: This subroutine initiates the VectorField_ object -! -!# Introduction -! This routine initiate the vector field object. -! `param` contains the information of parameters required to initiate the -! vector. There are essential and optional information. -! Essential information are described below. -! - `name` character defining the name of vector field -! - `spaceCompo` is the total degree of freedom or components -! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL - -INTERFACE - MODULE SUBROUTINE vField_Initiate1_old(obj, param, dom) - CLASS(VectorField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE vField_Initiate1_old -END INTERFACE - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -997,6 +991,23 @@ MODULE SUBROUTINE vField_Get11(obj, ivar, idof, VALUE, ivar_value, idof_value) END SUBROUTINE vField_Get11 END INTERFACE +!---------------------------------------------------------------------------- +! GetFEVariable@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-03-28 +! summary: Set single entry + +INTERFACE VectorFieldGetFEVariable + MODULE SUBROUTINE vField_GetFeVariable(obj, globalNode, VALUE, ivar) + CLASS(VectorField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + TYPE(FEVariable_), INTENT(INOUT) :: VALUE + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END SUBROUTINE vField_GetFeVariable +END INTERFACE VectorFieldGetFEVariable + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 b/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 index 8f5f73347..1e0d4d1af 100644 --- a/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 @@ -26,6 +26,8 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetVectorFieldParam +CHARACTER(*), PARAMETER :: myName = "SetVectorFieldParam()" +INTEGER(I4B) :: ierr TYPE(ParameterList_), POINTER :: sublist CALL SetAbstractFieldParam( & @@ -39,7 +41,16 @@ & global_n=global_n) sublist => NULL() -sublist => param%NewSubList(key=myprefix) +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF CALL Set( & & obj=sublist, & @@ -71,8 +82,9 @@ MODULE PROCEDURE vField_Initiate1 CHARACTER(*), PARAMETER :: myName = "vField_Initiate1()" +CHARACTER(1) :: names(1) TYPE(String) :: astr -INTEGER(I4B) :: nsd, tdof, ierr, spaceCompo, tNodes +INTEGER(I4B) :: nsd, tdof, ierr, tNodes TYPE(ParameterList_), POINTER :: sublist ! main @@ -93,17 +105,20 @@ CALL obj%DEALLOCATE() CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) -CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", VALUE=spaceCompo) +CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", & + & VALUE=obj%spaceCompo) + tNodes = dom%GetTotalNodes() -tdof = tNodes * spaceCompo +tdof = tNodes * obj%spaceCompo +names(1) (:) = astr%slice(1, 1) CALL AbstractNodeFieldSetParam(obj=obj, & & dof_tPhysicalVars=1_I4B, & & dof_storageFMT=NODES_FMT, & - & dof_spaceCompo=[spaceCompo], & + & dof_spaceCompo=[obj%spaceCompo], & & dof_timeCompo=[1_I4B], & & dof_tNodes=[tNodes], & - & dof_names_char=[astr%slice(1, 1)], & + & dof_names_char=names, & & tSize=tdof) nsd = dom%GetNSD() @@ -118,93 +133,6 @@ sublist => NULL() END PROCEDURE vField_Initiate1 -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE vField_Initiate1_old -CHARACTER(*), PARAMETER :: myName = "vField_Initiate" -INTEGER(I4B) :: ierr, storageFMT, tNodes(1), timeCompo(1), & - & spaceCompo(1) -CHARACTER(:), ALLOCATABLE :: char_var -CHARACTER(1) :: names_char(1) - -IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'VectorField_::obj is already initiated') -END IF - -CALL obj%checkEssentialParam(param) - -! engine -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) -ierr = param%get(key=myprefix//"/engine", VALUE=char_var) -obj%engine = char_var -DEALLOCATE (char_var) - -! name -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/name")) :: char_var) -ierr = param%get(key=myprefix//"/name", VALUE=char_var) -obj%name = char_var -names_char(1) (1:1) = char_var(1:1) -DEALLOCATE (char_var) - -! spaceCompo -ierr = param%get(key=myprefix//"/spaceCompo", VALUE=obj%spaceCompo) - -! fieldType -IF (param%isPresent(key=myprefix//"/fieldType")) THEN - ierr = param%get(key=myprefix//"/fieldType", VALUE=obj%fieldType) -ELSE - obj%fieldType = FIELD_TYPE_NORMAL -END IF - -! comm -ierr = param%get(key=myprefix//"/comm", VALUE=obj%comm) -ierr = param%get(key=myprefix//"/global_n", VALUE=obj%global_n) -ierr = param%get(key=myprefix//"/local_n", VALUE=obj%local_n) - -spaceCompo = obj%spaceCompo -timeCompo = 1 -storageFMT = FMT_NODES -obj%domain => dom -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - tNodes = 1 - obj%tSize = obj%domain%getTotalNodes() * obj%spaceCompo - IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%spaceCompo - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%spaceCompo - END IF -ELSE - tNodes = obj%domain%getTotalNodes() - obj%tSize = tNodes(1) * obj%spaceCompo - IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize - END IF -END IF - -CALL Initiate( & - & obj=obj%dof, & - & tNodes=tNodes, & - & names=names_char, & - & spaceCompo=spaceCompo, & - & timeCompo=timeCompo, & - & storageFMT=storageFMT) - -CALL Initiate(obj%realVec, obj%dof) - -obj%isInitiated = .TRUE. - -IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE vField_Initiate1_old - !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- diff --git a/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 b/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 index cee86409f..0262042ca 100644 --- a/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 +++ b/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 @@ -21,12 +21,12 @@ CONTAINS !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get1 +MODULE PROCEDURE vField_Get1 INTEGER(I4B) :: localNode -CHARACTER(*), PARAMETER :: myName = "vField_get1" +CHARACTER(*), PARAMETER :: myName = "vField_Get1" IF (.NOT. obj%isInitiated) & & CALL e%raiseError(modName//'::'//myName//" - "// & @@ -40,58 +40,58 @@ IF (PRESENT(globalNode)) THEN SELECT CASE (obj%fieldType) CASE (FIELD_TYPE_CONSTANT) - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%spaceCompo), & & VALUE=VALUE, & & nodenum=[1]) CASE (FIELD_TYPE_NORMAL) - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%spaceCompo), & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber([globalNode])) + & nodenum=obj%domain%GetLocalNodeNumber([globalNode])) END SELECT END IF IF (PRESENT(spaceCompo)) THEN - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=spaceCompo, & & VALUE=VALUE) END IF -END PROCEDURE vField_get1 +END PROCEDURE vField_Get1 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get2 -CALL getValue( & +MODULE PROCEDURE vField_Get2 +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%spaceCompo), & & VALUE=VALUE, & & force3D=force3D) -END PROCEDURE vField_get2 +END PROCEDURE vField_Get2 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get3 +MODULE PROCEDURE vField_Get3 REAL(DFP), ALLOCATABLE :: v(:) -CALL getValue( & +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%spaceCompo), & & VALUE=v, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) IF (PRESENT(force3D)) THEN CALL Reallocate(VALUE, 3, SIZE(globalNode)) @@ -102,88 +102,88 @@ END IF DEALLOCATE (v) -END PROCEDURE vField_get3 +END PROCEDURE vField_Get3 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get4 -CALL getValue( & +MODULE PROCEDURE vField_Get4 +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & ivar=1, & & idof=spaceCompo, & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) -END PROCEDURE vField_get4 + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) +END PROCEDURE vField_Get4 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get5 -CALL getValue( & +MODULE PROCEDURE vField_Get5 +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & ivar=1, & & idof=spaceCompo, & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) -END PROCEDURE vField_get5 + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) +END PROCEDURE vField_Get5 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get6 +MODULE PROCEDURE vField_Get6 INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%get(globalNode=globalNode, VALUE=VALUE) -END PROCEDURE vField_get6 +CALL obj%Get(globalNode=globalNode, VALUE=VALUE) +END PROCEDURE vField_Get6 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get7 +MODULE PROCEDURE vField_Get7 INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%get(globalNode=globalNode, VALUE=VALUE, spaceCompo=spaceCompo) -END PROCEDURE vField_get7 +CALL obj%Get(globalNode=globalNode, VALUE=VALUE, spaceCompo=spaceCompo) +END PROCEDURE vField_Get7 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get8 +MODULE PROCEDURE vField_Get8 REAL(DFP), ALLOCATABLE :: v(:) -CALL getValue( & +CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=arange(1, obj%spaceCompo), & & VALUE=v, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) VALUE = NodalVariable( & & RESHAPE(v, [obj%spaceCompo, SIZE(globalNode)]), & & TypeFEVariableVector, TypeFEVariableSpace) DEALLOCATE (v) -END PROCEDURE vField_get8 +END PROCEDURE vField_Get8 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get9 -CHARACTER(*), PARAMETER :: myName = "vField_get9" +MODULE PROCEDURE vField_Get9 +CHARACTER(*), PARAMETER :: myName = "vField_Get9" INTEGER(I4B) :: n n = obj%spaceCompo @@ -206,24 +206,24 @@ CALL e%raiseError(modName//'::'//myName//' - '// & & 'No case found for the type of value') END SELECT -END PROCEDURE vField_get9 +END PROCEDURE vField_Get9 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get10 +MODULE PROCEDURE vField_Get10 CALL GetValue( & & obj=obj%realvec, & & VALUE=VALUE%realvec) -END PROCEDURE vField_get10 +END PROCEDURE vField_Get10 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_get11 -CHARACTER(*), PARAMETER :: myName = "vField_get11" +MODULE PROCEDURE vField_Get11 +CHARACTER(*), PARAMETER :: myName = "vField_Get11" INTEGER(I4B) :: tsize INTEGER(I4B) :: tsize_value INTEGER(I4B) :: ii @@ -263,21 +263,29 @@ CALL VALUE%SetSingle(VALUE=avar, indx=indx2) END DO -END PROCEDURE vField_get11 +END PROCEDURE vField_Get11 + +!---------------------------------------------------------------------------- +! GetFEVariable +!---------------------------------------------------------------------------- + +MODULE PROCEDURE vField_GetFEVariable +CALL obj%Get(VALUE=VALUE, globalNode=globalNode) +END PROCEDURE vField_GetFEVariable !---------------------------------------------------------------------------- -! getPointerOfComponent +! GetPointerOfComponent !---------------------------------------------------------------------------- -MODULE PROCEDURE vField_getPointerOfComponent -CHARACTER(*), PARAMETER :: myName = "vField_getPointerOfComponent" +MODULE PROCEDURE vField_GetPointerOfComponent +CHARACTER(*), PARAMETER :: myName = "vField_GetPointerOfComponent" IF (spaceCompo .GT. obj%spaceCompo) & & CALL e%raiseError(modName//'::'//myName//" - "// & & 'given spaceCompo should be less than or equal to obj%spaceCompo') -ans => getPointer( & +ans => GetPointer( & & obj=obj%realvec, & & dofobj=obj%dof, & & idof=spaceCompo) -END PROCEDURE vField_getPointerOfComponent +END PROCEDURE vField_GetPointerOfComponent END SUBMODULE GetMethods From 99e4300ad986c2ff560e0d843b0ccc5900f84130 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 13:55:47 +0900 Subject: [PATCH 044/117] Updates in STVectorField - Adding VTK export support - Adding GetFEVariable method - Minor formatting - Fixes issue #193 for STVectorField and STVectorFieldLis --- .../STVectorField/src/STVectorField_Class.F90 | 106 +++++------ ...STVectorField_Class@ConstructorMethods.F90 | 129 +++---------- .../src/STVectorField_Class@GetMethods.F90 | 170 +++++++++--------- 3 files changed, 173 insertions(+), 232 deletions(-) diff --git a/src/modules/STVectorField/src/STVectorField_Class.F90 b/src/modules/STVectorField/src/STVectorField_Class.F90 index a2969fff2..b457a984c 100644 --- a/src/modules/STVectorField/src/STVectorField_Class.F90 +++ b/src/modules/STVectorField/src/STVectorField_Class.F90 @@ -60,15 +60,24 @@ MODULE STVectorField_Class INTEGER(I4B) :: timeCompo = 0_I4B CONTAINS PRIVATE - PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & - & stvField_checkEssentialParam + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & stvField_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => stvField_Initiate1 PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => stvField_Initiate2 PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => stvField_Deallocate FINAL :: stvField_Final + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: Display => stvField_Display PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => stvField_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => stvField_Export + + ! SET: + ! @SetMethods PROCEDURE, PASS(obj) :: Set1 => stvField_Set1 !! Set single entry PROCEDURE, PASS(obj) :: Set2 => stvField_Set2 @@ -101,6 +110,9 @@ MODULE STVectorField_Class & Set1, Set2, Set3, Set4, Set5, Set6, & & Set7, Set8, Set9, Set10, Set11, & & Set12, Set13, Set14, Set15 + + ! GET: + ! @GetMethods PROCEDURE, PASS(obj) :: Get1 => stvField_Get1 PROCEDURE, PASS(obj) :: Get2 => stvField_Get2 PROCEDURE, PASS(obj) :: Get3 => stvField_Get3 @@ -117,10 +129,14 @@ MODULE STVectorField_Class PROCEDURE, PUBLIC, PASS(obj) :: GetPointerOfComponent => & & stvField_GetPointerOfComponent !! Get the entries of STVector field + PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => & + & stvField_GetFeVariable + + ! SET: + ! @DirichletBCMethods PROCEDURE, PASS(obj) :: stvField_ApplyDirichletBC1 PROCEDURE, PASS(obj) :: stvField_ApplyDirichletBC2 - GENERIC, PUBLIC :: ApplyDirichletBC => & - & stvField_ApplyDirichletBC1, & + GENERIC, PUBLIC :: ApplyDirichletBC => stvField_ApplyDirichletBC1, & & stvField_ApplyDirichletBC2 END TYPE STVectorField_ @@ -160,18 +176,18 @@ END SUBROUTINE SetSTVectorFieldParam END INTERFACE !---------------------------------------------------------------------------- -! checkEssentialParam@ConstructorMethods +! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine check the essential parameters in param. +! summary: This routine Check the essential parameters in param. INTERFACE - MODULE SUBROUTINE stvField_checkEssentialParam(obj, param) + MODULE SUBROUTINE stvField_CheckEssentialParam(obj, param) CLASS(STVectorField_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE stvField_checkEssentialParam + END SUBROUTINE stvField_CheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- @@ -198,7 +214,7 @@ END SUBROUTINE stvField_checkEssentialParam MODULE SUBROUTINE stvField_Initiate1(obj, param, dom) CLASS(STVectorField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom END SUBROUTINE stvField_Initiate1 END INTERFACE STVectorFieldInitiate1 @@ -206,34 +222,6 @@ END SUBROUTINE stvField_Initiate1 ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- -!> authors: Vikas Sharma, Ph. D. -! date: 25 June 2021 -! summary: This subroutine initiates the space-time vector field -! -!# Introduction -! -! This routine initiate the space-time vector field object. -! `param` contains the information of parameters required to initiate the -! this field. -! There are essential and optional information. -! Essential information are described below. -! - `name` character defining the name of STvector field -! - `spaceCompo` is the total degree of freedom or components -! - `timeCompo` is the total degree of freedom or components -! - `fieldType` type of field type; FIELD_TYPE_CONSTANT, FIELD_TYPE_NORMAL - -INTERFACE - MODULE SUBROUTINE stvField_Initiate1_old(obj, param, dom) - CLASS(STVectorField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom - END SUBROUTINE stvField_Initiate1_old -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - !> author: Vikas Sharma, Ph. D. ! date: 2023-03-29 ! summary: Initiate2 @@ -256,7 +244,7 @@ END SUBROUTINE stvField_Initiate2 !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine deallocates the data stored inside the STVectorField_ obj +! summary: Deallocates the data stored inside the STVectorField_ obj INTERFACE STVectorFieldDeallocate MODULE SUBROUTINE stvField_Deallocate(obj) @@ -285,7 +273,7 @@ END SUBROUTINE stvField_Final INTERFACE STVectorField MODULE FUNCTION stvField_Constructor1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom TYPE(STVectorField_) :: ans END FUNCTION stvField_Constructor1 END INTERFACE STVectorField @@ -301,7 +289,7 @@ END FUNCTION stvField_Constructor1 INTERFACE STVectorField_Pointer MODULE FUNCTION stvField_Constructor_1(param, dom) RESULT(Ans) TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGet, INTENT(IN) :: dom + TYPE(Domain_), TARGET, INTENT(IN) :: dom CLASS(STVectorField_), POINTER :: ans END FUNCTION stvField_Constructor_1 END INTERFACE STVectorField_Pointer @@ -335,8 +323,8 @@ MODULE SUBROUTINE stvField_Import(obj, hdf5, group, dom, domains) CLASS(STVectorField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - TYPE(Domain_), TARGet, OPTIONAL, INTENT(IN) :: dom - TYPE(DomainPointer_), TARGet, OPTIONAL, INTENT(IN) :: domains(:) + TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom + TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE stvField_Import END INTERFACE STVectorFieldImport @@ -405,7 +393,7 @@ END SUBROUTINE stvField_Set1 INTERFACE MODULE SUBROUTINE stvField_Set2(obj, VALUE, scale, addContribution) - CLASS(STVectorField_), TARGet, INTENT(INOUT) :: obj + CLASS(STVectorField_), TARGET, INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:, :) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution @@ -535,7 +523,7 @@ END SUBROUTINE stvField_Set6 ! This soubroutine Sets the selected enties in space-time vector to a ! constant space-time nodal values. Here globalNode is the list of global ! node number. `value` is a rank2 array of real numbers. Its first index -! denotes the space component and second component denotes the time component. +! denotes the space component and second component denotes time component. ! !Effectively it does the following: ! @@ -595,7 +583,7 @@ END SUBROUTINE stvField_Set8 ! summary: This routine Sets the selected entries ! !# Introduction -! This routine Sets the selected components of selected nodes to a given value +! This routine Sets the selected components of selected nodes to given value ! ! STvector( spaceCompo, globalNode ) = value( : ) @@ -775,7 +763,7 @@ END SUBROUTINE stvField_Get1 ! summary: This routine Get all the entries of the space-time vector field ! !# Introduction -! This routine returns all the nodal values of a space-time nodal vector field. +! This routine returns all the nodal values of space-time nodal vector field. ! Here value is a rank3 array of reals. ! ! - Its first index denotes the spatial component @@ -805,7 +793,7 @@ END SUBROUTINE stvField_Get2 ! - The third index corresponds to the node number. ! !@note -! The size of third dimension of value should be equal to the size of globalNode. +! The size of third dimension of value should be equal to size of globalNode. !@endnote INTERFACE @@ -958,7 +946,8 @@ END SUBROUTINE stvField_Get10 ! summary: REturns the value INTERFACE -MODULE SUBROUTINE stvField_Get11(obj, ivar, idof, VALUE, ivar_value, idof_value) + MODULE SUBROUTINE stvField_Get11(obj, ivar, idof, VALUE, ivar_value, & + & idof_value) CLASS(STVectorField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar @@ -968,6 +957,23 @@ MODULE SUBROUTINE stvField_Get11(obj, ivar, idof, VALUE, ivar_value, idof_value) END SUBROUTINE stvField_Get11 END INTERFACE +!---------------------------------------------------------------------------- +! GetFEVariable@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-03-28 +! summary: Set single entry + +INTERFACE STVectorFieldGetFEVariable + MODULE SUBROUTINE stvField_GetFeVariable(obj, globalNode, VALUE, ivar) + CLASS(STVectorField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + TYPE(FEVariable_), INTENT(INOUT) :: VALUE + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END SUBROUTINE stvField_GetFeVariable +END INTERFACE STVectorFieldGetFEVariable + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- @@ -1007,8 +1013,8 @@ END SUBROUTINE stvField_ApplyDirichletBC2 ! summary: This routine returns pointer to a specific component INTERFACE - MODULE FUNCTION stvField_GetPointerOfComponent(obj, spaceCompo, timeCompo) & - & RESULT(ans) + MODULE FUNCTION stvField_GetPointerOfComponent(obj, spaceCompo, & + & timeCompo) RESULT(ans) CLASS(STVectorField_), INTENT(IN) :: obj INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo diff --git a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 index 980235baa..a9557f2e8 100644 --- a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 @@ -26,6 +26,8 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetSTVectorFieldParam +CHARACTER(*), PARAMETER :: myName = "SetSTVectorFieldParam()" +INTEGER(I4B) :: ierr TYPE(ParameterList_), POINTER :: sublist CALL SetAbstractFieldParam( & @@ -39,7 +41,16 @@ & global_n=global_n) sublist => NULL() -sublist => param%NewSubList(key=myprefix) +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF CALL Set( & & obj=sublist, & @@ -67,11 +78,11 @@ CHARACTER(*), PARAMETER :: myName = "stvField_checkEssentialParam" CALL AbstractFieldCheckEssentialParam(obj=obj, param=param, prefix=myprefix) IF (.NOT. param%IsPresent(key=myprefix//"/spaceCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'spaceCompo should be present in param.') END IF IF (.NOT. param%IsPresent(key=myprefix//"/timeCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & 'timeCompo should be present in param.') END IF END PROCEDURE stvField_CheckEssentialParam @@ -82,8 +93,9 @@ MODULE PROCEDURE stvField_Initiate1 CHARACTER(*), PARAMETER :: myName = "stvField_Initiate1()" +CHARACTER(1) :: names(1) TYPE(String) :: astr -INTEGER(I4B) :: nsd, tdof, ierr, spaceCompo, tNodes, timeCompo +INTEGER(I4B) :: nsd, tdof, ierr, tNodes TYPE(ParameterList_), POINTER :: sublist ! main @@ -93,29 +105,35 @@ IF (ierr .NE. 0_I4B) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + RETURN END IF IF (.NOT. ASSOCIATED(sublist)) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') + RETURN END IF CALL obj%CheckEssentialParam(sublist) CALL obj%DEALLOCATE() CALL GetValue(obj=sublist, prefix=myprefix, key="name", VALUE=astr) -CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", VALUE=spaceCompo) -CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", VALUE=timeCompo) +CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", & + & VALUE=obj%spaceCompo) +CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", & + & VALUE=obj%timeCompo) + tNodes = dom%GetTotalNodes() -tdof = tNodes * spaceCompo * timeCompo +tdof = tNodes * obj%spaceCompo * obj%timeCompo +names(1) (:) = astr%slice(1, 1) CALL AbstractNodeFieldSetParam(obj=obj, & & dof_tPhysicalVars=1_I4B, & & dof_storageFMT=NODES_FMT, & - & dof_spaceCompo=[spaceCompo], & - & dof_timeCompo=[timeCompo], & + & dof_spaceCompo=[obj%spaceCompo], & + & dof_timeCompo=[obj%timeCompo], & & dof_tNodes=[tNodes], & - & dof_names_char=[astr%slice(1, 1)], & + & dof_names_char=names, & & tSize=tdof) nsd = dom%GetNSD() @@ -130,97 +148,6 @@ sublist => NULL() END PROCEDURE stvField_Initiate1 -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE stvField_Initiate1_old -CHARACTER(*), PARAMETER :: myName = "stvField_Initiate1" -INTEGER(I4B) :: ierr, storageFMT, tNodes(1), spaceCompo(1), & - & timeCompo(1) -CHARACTER(:), ALLOCATABLE :: char_var -CHARACTER(1) :: names_char(1) - -! main program -IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'STVectorField_::obj is already initiated') -END IF - -CALL obj%CheckEssentialParam(param) - -! engine -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) -ierr = param%get(key=myprefix//"/engine", VALUE=char_var) -obj%engine = char_var -DEALLOCATE (char_var) - -! name -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/name")) :: char_var) -ierr = param%get(key=myprefix//"/name", VALUE=char_var) -obj%name = char_var -names_char(1) (1:1) = char_var(1:1) -DEALLOCATE (char_var) - -! fieldType -IF (param%isPresent(key=myprefix//"/fieldType")) THEN - ierr = param%get(key=myprefix//"/fieldType", VALUE=obj%fieldType) -ELSE - obj%fieldType = FIELD_TYPE_NORMAL -END IF - -! comm -ierr = param%get(key=myprefix//"/comm", VALUE=obj%comm) -ierr = param%get(key=myprefix//"/global_n", VALUE=obj%global_n) -ierr = param%get(key=myprefix//"/local_n", VALUE=obj%local_n) - -! timeCompo -ierr = param%get(key=myprefix//"/timeCompo", VALUE=obj%timeCompo) - -! spaceCompo -ierr = param%get(key=myprefix//"/spaceCompo", VALUE=obj%spaceCompo) - -timeCompo = obj%timeCompo -spaceCompo = obj%spaceCompo -storageFMT = FMT_NODES -obj%domain => dom -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - tNodes = 1 - obj%tSize = obj%domain%getTotalNodes() * obj%timeCompo * obj%spaceCompo - IF (obj%local_n .EQ. 0) THEN - obj%local_n = tNodes(1) * obj%timeCompo * obj%spaceCompo - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = tNodes(1) * obj%timeCompo * obj%spaceCompo - END IF -ELSE - tNodes = obj%domain%getTotalNodes() - obj%tSize = tNodes(1) * obj%timeCompo * obj%spaceCompo - IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize - END IF - IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize - END IF -END IF - -CALL Initiate( & - & obj=obj%dof, & - & tNodes=tNodes, & - & names=names_char, & - & spaceCompo=spaceCompo, & - & timeCompo=timeCompo, & - & storageFMT=storageFMT) - -CALL Initiate(obj%realVec, obj%dof) - -obj%isInitiated = .TRUE. - -IF (ALLOCATED(char_var)) DEALLOCATE (char_var) -END PROCEDURE stvField_Initiate1_old - !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- diff --git a/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 b/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 index 34bc94d4d..de41fb983 100644 --- a/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 +++ b/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 @@ -22,35 +22,35 @@ CONTAINS !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get1 +MODULE PROCEDURE stvField_Get1 IF (PRESENT(globalnode)) THEN SELECT CASE (obj%fieldType) CASE (FIELD_TYPE_CONSTANT) - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & - & idof=getIDOF(obj=obj%dof, ivar=1), & + & idof=GetIDOF(obj=obj%dof, ivar=1), & & VALUE=VALUE, & & storageFMT=NODES_FMT, & & nodenum=[1]) RETURN CASE (FIELD_TYPE_NORMAL) - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & - & idof=getIDOF(obj=obj%dof, ivar=1), & + & idof=GetIDOF(obj=obj%dof, ivar=1), & & VALUE=VALUE, & & storageFMT=NODES_FMT, & - & nodenum=obj%domain%getLocalNodeNumber([globalnode])) + & nodenum=obj%domain%GetLocalNodeNumber([globalnode])) RETURN END SELECT END IF IF (PRESENT(spacecompo) .AND. PRESENT(timecompo)) THEN - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & & ivar=1, & @@ -61,10 +61,10 @@ END IF IF (PRESENT(spacecompo)) THEN - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & - & idof=getIDOF( & + & idof=GetIDOF( & & obj=obj%dof, & & ivar=1, & & spacecompo=spacecompo, & @@ -75,10 +75,10 @@ END IF IF (PRESENT(timecompo)) THEN - CALL getValue( & + CALL GetValue( & & obj=obj%realvec, & & dofobj=obj%dof, & - & idof=getIDOF( & + & idof=GetIDOF( & & obj=obj%dof, & & ivar=1, & & timecompo=timecompo, & @@ -88,58 +88,58 @@ RETURN END IF -END PROCEDURE stvField_get1 +END PROCEDURE stvField_Get1 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get2 +MODULE PROCEDURE stvField_Get2 VALUE = RESHAPE( & - & get( & + & Get( & & obj=obj%realVec, & & datatype=1.0_DFP), & - & [obj%spaceCompo, obj%timeCompo, obj%domain%getTotalNodes()]) -END PROCEDURE stvField_get2 + & [obj%spaceCompo, obj%timeCompo, obj%domain%GetTotalNodes()]) +END PROCEDURE stvField_Get2 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get3 +MODULE PROCEDURE stvField_Get3 REAL(DFP), ALLOCATABLE :: v(:) -CALL getValue( & +CALL GetValue( & & obj=obj%realVec, & & dofobj=obj%dof, & - & idof=getIDOF(obj=obj%dof, ivar=1), & + & idof=GetIDOF(obj=obj%dof, ivar=1), & & VALUE=v, & & storageFMT=NODES_FMT, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) VALUE = RESHAPE(v, [obj%spaceCompo, obj%timeCompo, SIZE(globalNode)]) DEALLOCATE (v) -END PROCEDURE stvField_get3 +END PROCEDURE stvField_Get3 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get4 -CALL getValue( & +MODULE PROCEDURE stvField_Get4 +CALL GetValue( & & obj=obj%realVec, & & dofobj=obj%dof, & & ivar=1, & & spacecompo=spacecompo, & & timecompo=timecompo, & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) -END PROCEDURE stvField_get4 + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) +END PROCEDURE stvField_Get4 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get5 -CALL getValue( & +MODULE PROCEDURE stvField_Get5 +CALL GetValue( & & obj=obj%realVec, & & dofobj=obj%dof, & & ivar=1, & @@ -149,59 +149,59 @@ & spacecompo=spacecompo, & & timecompo=timecompo), & & VALUE=VALUE, & - & nodenum=obj%domain%getLocalNodeNumber(globalNode)) -END PROCEDURE stvField_get5 + & nodenum=obj%domain%GetLocalNodeNumber(globalNode)) +END PROCEDURE stvField_Get5 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get6 +MODULE PROCEDURE stvField_Get6 INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%get(globalNode=globalNode, VALUE=VALUE) -END PROCEDURE stvField_get6 +CALL obj%Get(globalNode=globalNode, VALUE=VALUE) +END PROCEDURE stvField_Get6 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get7 +MODULE PROCEDURE stvField_Get7 INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%get( & +CALL obj%Get( & & globalNode=globalNode, & & VALUE=VALUE, & & spaceCompo=spaceCompo, & & timeCompo=timeCompo) -END PROCEDURE stvField_get7 +END PROCEDURE stvField_Get7 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get8 +MODULE PROCEDURE stvField_Get8 REAL(DFP), ALLOCATABLE :: val(:, :, :) -CALL obj%get(VALUE=val, globalNode=[globalNode]) +CALL obj%Get(VALUE=val, globalNode=[globalNode]) VALUE = val(:, :, 1) DEALLOCATE (val) -END PROCEDURE stvField_get8 +END PROCEDURE stvField_Get8 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get9 +MODULE PROCEDURE stvField_Get9 REAL(DFP), ALLOCATABLE :: m3a(:, :, :), m3b(:, :, :) -CALL obj%get(VALUE=m3b, globalNode=globalNode) +CALL obj%Get(VALUE=m3b, globalNode=globalNode) ! Here m3b is in (i, a, J) format, ! so we have to swap the dimensions to (i,J,a) @@ -211,14 +211,14 @@ & TypeFEVariableSpacetime) DEALLOCATE (m3a, m3b) -END PROCEDURE stvField_get9 +END PROCEDURE stvField_Get9 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get10 -CHARACTER(*), PARAMETER :: myName = "stvField_get10" +MODULE PROCEDURE stvField_Get10 +CHARACTER(*), PARAMETER :: myName = "stvField_Get10" INTEGER(I4B) :: case_id INTEGER(I4B) :: tNodes INTEGER(I4B) :: ii @@ -239,9 +239,9 @@ & "") END IF -tNodes = obj%domain%getTotalNodes() +tNodes = obj%domain%GetTotalNodes() -IF (tNodes .NE. VALUE%domain%getTotalNodes()) THEN +IF (tNodes .NE. VALUE%domain%GetTotalNodes()) THEN CALL e%raiseError(modName//'::'//myName//' - '// & & 'tNodes of STVectorFieldLis_::obj and'// & & ' tNodes of AbstractNodeField_::value are not same') @@ -283,32 +283,32 @@ SELECT TYPE (VALUE) CLASS IS (ScalarField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) - CALL obj%get(VALUE=avar, globalnode=globalnode, & + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=timeCompo) CALL VALUE%set(VALUE=avar, globalnode=globalnode) END DO CLASS IS (STScalarField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) - CALL obj%get(VALUE=avar, globalnode=globalnode, & + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=timeCompo) CALL VALUE%set(VALUE=avar, globalnode=globalnode, timeCompo=timeCompo) END DO CLASS IS (VectorField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) - CALL obj%get(VALUE=avar, globalnode=globalnode, & + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=timeCompo) CALL VALUE%set(VALUE=avar, globalnode=globalnode, spaceCompo=spaceCompo) END DO CLASS IS (STVectorField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) - CALL obj%get(VALUE=avar, globalnode=globalnode, & + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=timeCompo) CALL VALUE%set(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=timeCompo) @@ -326,9 +326,9 @@ CLASS IS (STScalarField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) DO jj = 1, obj%timeCompo - CALL obj%get(VALUE=avar, globalnode=globalnode, & + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=jj) CALL VALUE%set(VALUE=avar, globalnode=globalnode, timeCompo=jj) END DO @@ -336,9 +336,9 @@ CLASS IS (STVectorField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) DO jj = 1, obj%timeCompo - CALL obj%get(VALUE=avar, globalnode=globalnode, & + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=jj) CALL VALUE%set(VALUE=avar, globalnode=globalnode, & & spaceCompo=spaceCompo, timeCompo=jj) @@ -357,9 +357,9 @@ CLASS IS (VectorField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) DO jj = 1, obj%spaceCompo - CALL obj%get(VALUE=avar, globalnode=globalnode, & + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=jj, timeCompo=timeCompo) CALL VALUE%set(VALUE=avar, globalnode=globalnode, spaceCompo=jj) END DO @@ -367,9 +367,9 @@ CLASS IS (STVectorField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) DO jj = 1, obj%spaceCompo - CALL obj%get(VALUE=avar, globalnode=globalnode, & + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=jj, timeCompo=timeCompo) CALL VALUE%set(VALUE=avar, globalnode=globalnode, & & spaceCompo=jj, timeCompo=timeCompo) @@ -388,10 +388,10 @@ CLASS IS (STVectorField_) DO ii = 1, tNodes - globalnode = obj%domain%getGlobalNodeNumber(localNode=ii) + globalnode = obj%domain%GetGlobalNodeNumber(localNode=ii) DO jj = 1, obj%timeCompo DO kk = 1, obj%spaceCompo - CALL obj%get(VALUE=avar, globalnode=globalnode, & + CALL obj%Get(VALUE=avar, globalnode=globalnode, & & spaceCompo=kk, timeCompo=jj) CALL VALUE%set(VALUE=avar, globalnode=globalnode, & & spaceCompo=kk, timeCompo=jj) @@ -410,14 +410,14 @@ & 'No case found for given arguments') END SELECT -END PROCEDURE stvField_get10 +END PROCEDURE stvField_Get10 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_get11 -CHARACTER(*), PARAMETER :: myName = "stvField_get11" +MODULE PROCEDURE stvField_Get11 +CHARACTER(*), PARAMETER :: myName = "stvField_Get11" INTEGER(I4B) :: tsize INTEGER(I4B) :: tsize_value INTEGER(I4B) :: ii @@ -457,14 +457,14 @@ CALL VALUE%SetSingle(VALUE=avar, indx=indx2) END DO -END PROCEDURE stvField_get11 +END PROCEDURE stvField_Get11 !---------------------------------------------------------------------------- -! getPointerOfComponent +! GetPointerOfComponent !---------------------------------------------------------------------------- -MODULE PROCEDURE stvField_getPointerOfComponent -CHARACTER(*), PARAMETER :: myName = "stvField_getPointerOfComponent" +MODULE PROCEDURE stvField_GetPointerOfComponent +CHARACTER(*), PARAMETER :: myName = "stvField_GetPointerOfComponent" IF (spaceCompo .GT. obj%spaceCompo .OR. timeCompo .GT. obj%timeCompo) THEN CALL e%raiseError(modName//'::'//myName//" - "// & @@ -472,7 +472,7 @@ & ' or equal to obj%spaceCompo or obj%timeCompo') END IF -ans => getPointer( & +ans => GetPointer( & & obj=obj%realVec, & & dofobj=obj%dof, & & idof=GetIDOF( & @@ -481,7 +481,15 @@ & spacecompo=spacecompo, & & timecompo=timecompo)) -END PROCEDURE stvField_getPointerOfComponent +END PROCEDURE stvField_GetPointerOfComponent + +!---------------------------------------------------------------------------- +! GetFEVariable +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stvField_GetFEVariable +CALL obj%Get(VALUE=VALUE, globalNode=globalNode) +END PROCEDURE stvField_GetFEVariable !---------------------------------------------------------------------------- ! From aa7efd8b38fe8c54269271dc8ce86d827f614b5b Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 17:51:33 +0900 Subject: [PATCH 045/117] Update in AbstractField_ - Adding AbstractFieldInitiate_2 method --- .../AbstractField/src/AbstractField_Class.F90 | 25 +- ...AbstractField_Class@ConstructorMethods.F90 | 114 ++- .../src/AbstractField_Class@IOMethods.F90 | 4 +- .../src/AbstractField_Class@Methods.F90 | 758 ------------------ 4 files changed, 126 insertions(+), 775 deletions(-) delete mode 100644 src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index f6ec1a755..bc621d26a 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -273,14 +273,31 @@ END SUBROUTINE SetAbstractFieldParam ! date: 2023-09-22 ! summary: Initiate the field by reading param and given domain -INTERFACE - MODULE SUBROUTINE AbstractFieldInitiate(obj, param, dom, prefix) +INTERFACE AbstractFieldInitiate + MODULE SUBROUTINE AbstractFieldInitiate_1(obj, param, dom, prefix) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractFieldInitiate -END INTERFACE + END SUBROUTINE AbstractFieldInitiate_1 +END INTERFACE AbstractFieldInitiate + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Initiate the field by reading param and given domain + +INTERFACE AbstractFieldInitiate + MODULE SUBROUTINE AbstractFieldInitiate_2(obj, param, dom, prefix) + CLASS(AbstractField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) + CHARACTER(*), INTENT(IN) :: prefix + END SUBROUTINE AbstractFieldInitiate_2 +END INTERFACE AbstractFieldInitiate !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods diff --git a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 index 14c7cffbe..e30f96c9e 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 @@ -103,11 +103,16 @@ ! Initiate !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractFieldInitiate -CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate()" +MODULE PROCEDURE AbstractFieldInitiate_1 +CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate_1()" TYPE(ParameterList_), POINTER :: sublist INTEGER(I4B) :: ierr +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractFieldInitiate()') +#endif + ! main sublist => NULL() ierr = param%GetSubList(key=prefix, sublist=sublist) @@ -128,16 +133,92 @@ & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') END IF -obj%isInitiated = .TRUE. -CALL GetValue(obj=sublist, prefix=prefix, key="fieldType", VALUE=obj%fieldType) -CALL GetValue(obj=sublist, prefix=prefix, key="name", VALUE=obj%name) -CALL GetValue(obj=sublist, prefix=prefix, key="engine", VALUE=obj%engine) -CALL GetValue(obj=sublist, prefix=prefix, key="comm", VALUE=obj%comm) -CALL GetValue(obj=sublist, prefix=prefix, key="global_n", VALUE=obj%global_n) -CALL GetValue(obj=sublist, prefix=prefix, key="local_n", VALUE=obj%local_n) +CALL AbstractFieldInitiate_Help1(obj, sublist, prefix) obj%domain => dom sublist => NULL() -END PROCEDURE AbstractFieldInitiate + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractFieldInitiate()') +#endif +END PROCEDURE AbstractFieldInitiate_1 + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractFieldInitiate_2 +CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate_2()" +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr, ii, tsize +LOGICAL(LGT) :: isOK + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractFieldInitiate()') +#endif + +! main +sublist => NULL() +ierr = param%GetSubList(key=prefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + RETURN +END IF + +! NOTE: We should not call deallocate in abstract classes. +! This is because, in concrete classes we may set some +! parameters before calling this method. +! All those parameters will be gone if we call deallocate +! here. +! CALL obj%DEALLOCATE() + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') + RETURN +END IF + +CALL AbstractFieldInitiate_Help1(obj, sublist, prefix) + +tsize = SIZE(dom) +ALLOCATE (obj%domains(tsize)) +DO ii = 1, tsize + isOK = ASSOCIATED(dom(ii)%ptr) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: dom('//tostring(ii)//') is not ASSOCIATED.') + RETURN + END IF + obj%domains(ii)%ptr => dom(ii)%ptr +END DO + +sublist => NULL() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractFieldInitiate()') +#endif +END PROCEDURE AbstractFieldInitiate_2 + +!---------------------------------------------------------------------------- +! AbstractFieldInitiate_Help1 +!---------------------------------------------------------------------------- + +SUBROUTINE AbstractFieldInitiate_Help1(obj, param, prefix) + CLASS(AbstractField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), INTENT(IN) :: prefix + + obj%isInitiated = .TRUE. + CALL GetValue(obj=param, prefix=prefix, key="fieldType", VALUE=obj%fieldType) + CALL GetValue(obj=param, prefix=prefix, key="name", VALUE=obj%name) + CALL GetValue(obj=param, prefix=prefix, key="engine", VALUE=obj%engine) + CALL GetValue(obj=param, prefix=prefix, key="comm", VALUE=obj%comm) + CALL GetValue(obj=param, prefix=prefix, key="global_n", VALUE=obj%global_n) + CALL GetValue(obj=param, prefix=prefix, key="local_n", VALUE=obj%local_n) +END SUBROUTINE AbstractFieldInitiate_Help1 !---------------------------------------------------------------------------- ! @@ -147,9 +228,15 @@ CHARACTER(*), PARAMETER :: myName = "aField_Initiate2" INTEGER(I4B) :: ii, tsize +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + IF (.NOT. obj2%isInitiated .OR. obj%isInitiated) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Either obj is already initiated or obj2 is not initiated!') + & '[INTERNAL ERROR] :: Either obj is already initiated or '// & + & ' obj2 is not initiated.') END IF obj%isInitiated = obj2%isInitiated obj%fieldType = obj2%fieldType @@ -171,6 +258,11 @@ obj%domains(ii)%ptr => obj2%domains(ii)%ptr END DO END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif END PROCEDURE aField_Initiate2 !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 index 241908c01..11dfd68a6 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@IOMethods.F90 @@ -105,7 +105,7 @@ MODULE PROCEDURE aField_Export CHARACTER(*), PARAMETER :: myName = "aField_Export" -TYPE(String) :: dname, matprop +TYPE(String) :: dname IF (.NOT. obj%isInitiated) THEN CALL e%raiseError(modName//'::'//myName//" - "// & @@ -182,7 +182,7 @@ MODULE PROCEDURE aField_Import CHARACTER(*), PARAMETER :: myName = "aField_Import" -TYPE(String) :: strval, dsetname, matrixProp +TYPE(String) :: strval, dsetname CALL e%raiseInformation(modName//'::'//myName//' - '// & & '[START] Import()') diff --git a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 deleted file mode 100644 index 67115abe4..000000000 --- a/src/submodules/AbstractField/src/AbstractField_Class@Methods.F90 +++ /dev/null @@ -1,758 +0,0 @@ -! 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(AbstractField_Class) Methods -USE BaseMethod -USE FPL_Method -IMPLICIT NONE -CONTAINS - -!---------------------------------------------------------------------------- -! CheckEssentialParam -!---------------------------------------------------------------------------- - -MODULE PROCEDURE AbstractFieldCheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "AbstractFieldCheckEssentialParam()" -TYPE(String) :: astr -TYPE(String), ALLOCATABLE :: essentialParam(:) -INTEGER(I4B) :: ii - -astr = "/name/engine/fieldType/comm/local_n/global_n" -CALL astr%Split(essentialParam, sep="/") -CALL CheckEssentialParam( & - & obj=param, & - & keys=essentialParam, & - & prefix=prefix, & - & myName=myName, & - & modName=modName) -! INFO: CheckEssentialParam param is defined in easifemClasses FPL_Method - -IF (ALLOCATED(essentialParam)) THEN - DO ii = 1, SIZE(essentialParam) - essentialParam(ii) = "" - END DO - DEALLOCATE (essentialParam) -END IF -astr = "" -END PROCEDURE AbstractFieldCheckEssentialParam - -!---------------------------------------------------------------------------- -! SetScalarFieldParam -!---------------------------------------------------------------------------- - -MODULE PROCEDURE SetAbstractFieldParam -TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr -CHARACTER(*), PARAMETER :: myName = "SetAbstractFieldParam()" -LOGICAL(LGT) :: isSublist - -sublist => NULL() - -! Create a new sublist -isSublist = param%isSubList(prefix) - -IF (isSublist) THEN - ierr = param%GetSubList(key=prefix, sublist=sublist) - IF (ierr .NE. 0) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') - END IF -ELSE - sublist => param%NewSubList(key=prefix) -END IF - -IF (.NOT. ASSOCIATED(sublist)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') -END IF - -CALL Set(obj=sublist, datatype="Char", prefix=prefix, key="name", VALUE=name) - -CALL Set(obj=sublist, datatype="Char", prefix=prefix, key="engine", & - & VALUE=engine) - -CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="fieldType", & - & VALUE=input(option=fieldType, default=FIELD_TYPE_NORMAL)) - -CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="comm", & - & VALUE=input(option=fieldType, default=0_I4B)) - -CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="local_n", & - & VALUE=input(option=local_n, default=0_I4B)) - -CALL Set(obj=sublist, datatype=TypeIntI4B, prefix=prefix, key="global_n", & - & VALUE=input(option=global_n, default=0_I4B)) - -sublist => NULL() -END PROCEDURE SetAbstractFieldParam - -!---------------------------------------------------------------------------- -! Display -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_Display -INTEGER(I4B) :: ii - -CALL Display("#"//TRIM(msg), unitNo=unitNo) - -IF (obj%isInitiated) THEN - CALL Display("# isInitiated : TRUE", unitNo=unitNo) -ELSE - CALL Display("# isInitiated : FALSE, Nothing to Display!", unitNo=unitNo) - RETURN -END IF - -CALL Display(obj%name//'', msg="# name : ", unitNo=unitNo) - -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - CALL Display("# fieldType : CONSTANT", unitNo=unitNo) -ELSE - CALL Display("# fieldType : NORMAL", unitNo=unitNo) -END IF - -CALL Display(obj%engine, msg='# engine : ', unitNo=unitNo) -CALL Display(obj%comm, msg='# comm: ', unitNo=unitNo) -CALL Display(obj%myRank, msg='# myRank: ', unitNo=unitNo) -CALL Display(obj%numProcs, msg='# numProcs: ', unitNo=unitNo) -CALL Display(obj%global_n, msg='# global_n: ', unitNo=unitNo) -CALL Display(obj%local_n, msg='# local_n: ', unitNo=unitNo) -CALL Display(obj%is, msg='# is: ', unitNo=unitNo) -CALL Display(obj%ie, msg='# ie: ', unitNo=unitNo) -CALL Display(obj%lis_ptr, msg='# lis_ptr: ', unitNo=unitNo) - -IF (ASSOCIATED(obj%domain)) THEN - CALL Display("# domain : ASSOCIATED", unitNo=unitNo) -ELSE - CALL Display("# domain : NOT ASSOCIATED", unitNo=unitNo) -END IF -! -IF (ALLOCATED(obj%domains)) THEN - CALL Display("# domains : ALLOCATED [" & - & //TOSTRING(SIZE(obj%domains)) & - & //"]", unitNo=unitNo) - DO ii = 1, SIZE(obj%domains) - IF (ASSOCIATED(obj%domains(ii)%ptr)) THEN - CALL Display("# domains("//TOSTRING(ii) & - & //")%ptr : ASSOCIATED", unitNo=unitNo) - ELSE - CALL Display("# domains("//TOSTRING(ii) & - & //")%ptr : NOT ASSOCIATED", unitNo=unitNo) - END IF - END DO -ELSE - CALL Display("# domains : NOT ALLOCATED", unitNo=unitNo) -END IF - -END PROCEDURE aField_Display - -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE AbstractFieldInitiate -CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate()" -TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr - -! main -sublist => NULL() -ierr = param%GetSubList(key=prefix, sublist=sublist) -IF (ierr .NE. 0_I4B) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') -END IF - -! NOTE: We should not call deallocate in abstract classes. -! This is because, in concrete classes we may set some -! parameters before calling this method. -! All those parameters will be gone if we call deallocate -! here. -! CALL obj%DEALLOCATE() - -IF (.NOT. ASSOCIATED(sublist)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') -END IF - -obj%isInitiated = .TRUE. -CALL GetValue(obj=sublist, prefix=prefix, key="fieldType", VALUE=obj%fieldType) -CALL GetValue(obj=sublist, prefix=prefix, key="name", VALUE=obj%name) -CALL GetValue(obj=sublist, prefix=prefix, key="engine", VALUE=obj%engine) -CALL GetValue(obj=sublist, prefix=prefix, key="comm", VALUE=obj%comm) -CALL GetValue(obj=sublist, prefix=prefix, key="global_n", VALUE=obj%global_n) -CALL GetValue(obj=sublist, prefix=prefix, key="local_n", VALUE=obj%local_n) -obj%domain => dom -sublist => NULL() -END PROCEDURE AbstractFieldInitiate - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_Initiate2 -CHARACTER(*), PARAMETER :: myName = "aField_Initiate2" -INTEGER(I4B) :: ii, tsize - -IF (.NOT. obj2%isInitiated .OR. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Either obj is already initiated or obj2 is not initiated!') -END IF -obj%isInitiated = obj2%isInitiated -obj%fieldType = obj2%fieldType -obj%name = obj2%name -obj%engine = obj2%engine -obj%comm = obj2%comm -obj%myRank = obj2%myRank -obj%numProcs = obj2%numProcs -obj%global_n = obj2%global_n -obj%local_n = obj2%local_n -obj%is = obj2%is -obj%ie = obj2%ie -obj%lis_ptr = obj2%lis_ptr -obj%domain => obj2%domain -IF (ALLOCATED(obj2%domains)) THEN - tsize = SIZE(obj2%domains) - ALLOCATE (obj%domains(tsize)) - DO ii = 1, tsize - obj%domains(ii)%ptr => obj2%domains(ii)%ptr - END DO -END IF -END PROCEDURE aField_Initiate2 - -!---------------------------------------------------------------------------- -! Deallocate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_Deallocate -INTEGER(I4B) :: ii -obj%name = "" -obj%engine = "" -obj%isInitiated = .FALSE. -obj%fieldType = FIELD_TYPE_NORMAL -obj%comm = 0 -obj%myRank = 0 -obj%numProcs = 1 -obj%global_n = 0 -obj%local_n = 0 -obj%is = 0 -obj%ie = 0 -obj%lis_ptr = 0 -obj%domain => NULL() -IF (ALLOCATED(obj%domains)) THEN - DO ii = 1, SIZE(obj%domains) - obj%domains(ii)%ptr => NULL() - END DO - DEALLOCATE (obj%domains) -END IF -END PROCEDURE aField_Deallocate - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE FIELD_TYPE_NUMBER -SELECT CASE (TRIM(name)) -CASE ("NORMAL") - ans = FIELD_TYPE_NORMAL -CASE ("CONSTANT") - ans = FIELD_TYPE_CONSTANT -CASE ("CONSTANT_SPACE") - ans = FIELD_TYPE_CONSTANT_SPACE -CASE ("CONSTANT_TIME") - ans = FIELD_TYPE_CONSTANT_TIME -END SELECT -END PROCEDURE FIELD_TYPE_NUMBER - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE FIELD_TYPE_NAME -! -SELECT CASE (id) -CASE (FIELD_TYPE_NORMAL) - ans = "NORMAL" -CASE (FIELD_TYPE_CONSTANT) - ans = "CONSTANT" -CASE (FIELD_TYPE_CONSTANT_SPACE) - ans = "CONSTANT_SPACE" -CASE (FIELD_TYPE_CONSTANT_TIME) - ans = "CONSTANT_TIME" -END SELECT -END PROCEDURE FIELD_TYPE_NAME - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_WriteData_hdf5 -CHARACTER(*), PARAMETER :: myName = "aField_WriteData_hdf5" -CALL e%raiseError(modName//'::'//myName//' - '// & - & 'This method should be implemented by children of AbstractField_') -END PROCEDURE aField_WriteData_hdf5 - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_WriteData_vtk -CHARACTER(*), PARAMETER :: myName = "aField_WriteData_vtk" -CALL e%raiseError(modName//'::'//myName//' - '// & - & 'This method should be implemented by children of AbstractField_') -END PROCEDURE aField_WriteData_vtk - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE GetParam -USE AbstractNodeField_Class, ONLY: AbstractNodeField_ -USE AbstractMatrixField_Class, ONLY: AbstractMatrixField_ - -CHARACTER(*), PARAMETER :: myName = "GetParam" -INTEGER(I4B) :: ii - -IF (PRESENT(isInitiated)) isInitiated = obj%isInitiated -IF (PRESENT(fieldType)) fieldType = obj%fieldType -IF (PRESENT(name)) name = obj%name%chars() -IF (PRESENT(engine)) engine = obj%engine%chars() -IF (PRESENT(comm)) comm = obj%comm -IF (PRESENT(myRank)) myRank = obj%myRank -IF (PRESENT(numProcs)) numProcs = obj%numProcs -IF (PRESENT(global_n)) global_n = obj%global_n -IF (PRESENT(local_n)) local_n = obj%local_n -IF (PRESENT(is)) is = obj%is -IF (PRESENT(ie)) ie = obj%ie -IF (PRESENT(lis_ptr)) lis_ptr = obj%lis_ptr -IF (PRESENT(domain)) domain => obj%domain - -IF (PRESENT(domains)) THEN - IF (.NOT. ALLOCATED(obj%domains)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'AbstractField_::obj%domains is not allocated ') - END IF - - IF (SIZE(obj%domains) .NE. SIZE(domains)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'AbstractField_::obj%domains size is not same as size of domains') - END IF - - DO ii = 1, SIZE(domains) - domains(ii)%ptr => obj%domains(ii)%ptr - END DO -END IF - -SELECT TYPE (obj) -CLASS IS (AbstractNodeField_) - IF (PRESENT(tSize)) tSize = obj%tSize - IF (PRESENT(realVec)) realVec = obj%realVec - IF (PRESENT(dof)) dof = obj%dof -CLASS IS (AbstractMatrixField_) - IF (PRESENT(isPMatInitiated)) isPMatInitiated = obj%isPMatInitiated -END SELECT - -END PROCEDURE GetParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE SetParam -USE AbstractNodeField_Class, ONLY: AbstractNodeField_ -USE AbstractMatrixField_Class, ONLY: AbstractMatrixField_ - -CHARACTER(*), PARAMETER :: myName = "SetParam" -INTEGER(I4B) :: ii - -IF (PRESENT(isInitiated)) obj%isInitiated = isInitiated -IF (PRESENT(fieldType)) obj%fieldType = fieldType -IF (PRESENT(name)) obj%name = TRIM(name) -IF (PRESENT(engine)) obj%engine = TRIM(engine) -IF (PRESENT(comm)) obj%comm = comm -IF (PRESENT(myRank)) obj%myRank = myRank -IF (PRESENT(numProcs)) obj%numProcs = numProcs -IF (PRESENT(global_n)) obj%global_n = global_n -IF (PRESENT(local_n)) obj%local_n = local_n -IF (PRESENT(is)) obj%is = is -IF (PRESENT(ie)) obj%ie = ie -IF (PRESENT(lis_ptr)) obj%lis_ptr = lis_ptr -IF (PRESENT(domain)) obj%domain => domain -IF (PRESENT(domains)) THEN - IF (.NOT. ALLOCATED(obj%domains)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'AbstractField_::Obj%domains is not allocated ') - END IF - - IF (SIZE(obj%domains) .NE. SIZE(domains)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'AbstractField_::Obj%domains size is not same as size of domains') - END IF - - DO ii = 1, SIZE(domains) - obj%domains(ii)%ptr => domains(ii)%ptr - END DO -END IF - -SELECT TYPE (obj) -CLASS IS (AbstractNodeField_) - IF (PRESENT(tSize)) obj%tSize = tSize - IF (PRESENT(realVec)) obj%realVec = realVec - IF (PRESENT(dof)) obj%dof = dof -CLASS IS (AbstractMatrixField_) - IF (PRESENT(isPMatInitiated)) obj%isPMatInitiated = isPMatInitiated -END SELECT -END PROCEDURE SetParam - -!---------------------------------------------------------------------------- -! Export -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_Export -CHARACTER(*), PARAMETER :: myName = "aField_Export" -TYPE(String) :: dname, matprop - -IF (.NOT. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Instnace of MatrixField_ is not initiated') -END IF - -! Check -IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') -END IF - -! Check -IF (.NOT. hdf5%isWrite()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have write permission') -END IF - -! fieldType -dname = TRIM(group)//"/fieldType" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=STRING(FIELD_TYPE_NAME(obj%fieldType))) - -! name -dname = TRIM(group)//"/name" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%name) - -! engine -dname = TRIM(group)//"/engine" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%engine) - -! comm -dname = TRIM(group)//"/comm" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%comm) - -! myRank -dname = TRIM(group)//"/myRank" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%myRank) - -! numProcs -dname = TRIM(group)//"/numProcs" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%numProcs) - -! local_n -dname = TRIM(group)//"/local_n" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%local_n) - -! global_n -dname = TRIM(group)//"/global_n" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%global_n) - -! is -dname = TRIM(group)//"/is" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%is) - -! ie -dname = TRIM(group)//"/ie" -CALL hdf5%WRITE(dsetname=TRIM(dname%chars()), & - & vals=obj%ie) - -END PROCEDURE aField_Export - -!---------------------------------------------------------------------------- -! aField_Import -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_Import -CHARACTER(*), PARAMETER :: myName = "aField_Import" -TYPE(String) :: strval, dsetname, matrixProp - -CALL e%raiseInformation(modName//'::'//myName//' - '// & - & '[START] Import()') - -! main program -IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'The instance of AbstractField_ is already initiated') -END IF - -! Check -IF (.NOT. hdf5%isOpen()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') -END IF - -! Check -IF (.NOT. hdf5%isRead()) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have read permission') -END IF - -! fieldType -dsetname = TRIM(group)//"/fieldType" -IF (hdf5%pathExists(dsetname%chars())) THEN - CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) - obj%fieldType = FIELD_TYPE_NUMBER(strval%chars()) -ELSE - obj%fieldType = FIELD_TYPE_NORMAL -END IF - -! name -dsetname = TRIM(group)//"/name" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'The dataset name should be present') -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%name) -END IF - -! engine -dsetname = TRIM(group)//"/engine" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%engine = "NATIVE_SERIAL" -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%engine) -END IF - -! comm -dsetname = TRIM(group)//"/comm" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%comm = 0 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%comm) -END IF - -! myRank -dsetname = TRIM(group)//"/myRank" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%myRank = 0 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%myRank) -END IF - -! numProcs -dsetname = TRIM(group)//"/numProcs" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%numProcs = 1 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%numProcs) -END IF - -! global_n -dsetname = TRIM(group)//"/global_n" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%global_n = 1 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%global_n) -END IF - -! local_n -dsetname = TRIM(group)//"/local_n" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%local_n = 1 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%local_n) -END IF - -! is -dsetname = TRIM(group)//"/is" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%is = 1 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%is) -END IF - -! ie -dsetname = TRIM(group)//"/ie" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - obj%ie = 1 -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%ie) -END IF - -IF (ASSOCIATED(obj%domain)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'obj%domain is associated, deallocate first') -END IF - -IF (ALLOCATED(obj%domains)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'obj%domains is allocated, deallocate first') -END IF - -IF (PRESENT(dom)) THEN - obj%domain => dom -ELSE IF (PRESENT(domains)) THEN - ALLOCATE (obj%domains(2)) - obj%domains(1)%ptr => domains(1)%ptr - obj%domains(2)%ptr => domains(2)%ptr -ELSE - CALL e%raiseError(modName//'::'//myName//" - "// & - & "For non-rectangle matrix dom should be present, "// & - & "for rectangle matrix matrix domains should be present") -END IF - -obj%isInitiated = .TRUE. - -CALL e%raiseInformation(modName//'::'//myName//' - '// & -& '[END] Import()') - -END PROCEDURE aField_Import - -!---------------------------------------------------------------------------- -! GetTotalPhysicalVars -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTotalPhysicalVars -CHARACTER(*), PARAMETER :: myName = "aField_GetTotalPhysicalVars()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& - & 'child classes') -END PROCEDURE aField_GetTotalPhysicalVars - -!---------------------------------------------------------------------------- -! aField_GetPhysicalNames -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetPhysicalNames -CHARACTER(*), PARAMETER :: myName = "aField_GetNames()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & - & " child classes.") -END PROCEDURE aField_GetPhysicalNames - -!---------------------------------------------------------------------------- -! GetSpaceCompo -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetSpaceCompo -CHARACTER(*), PARAMETER :: myName = "aField_GetSpaceCompo()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & - & " child classes.") -END PROCEDURE aField_GetSpaceCompo - -!---------------------------------------------------------------------------- -! GetTimeCompo -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTimeCompo -CHARACTER(*), PARAMETER :: myName = "aField_GetTimeCompo" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & - & " child classes.") -END PROCEDURE aField_GetTimeCompo - -!---------------------------------------------------------------------------- -! GetStorageFMT -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetStorageFMT -CHARACTER(*), PARAMETER :: myName = "aField_GetStorageFMT" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & - & " child classes.") -END PROCEDURE aField_GetStorageFMT - -!---------------------------------------------------------------------------- -! GetTotalDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTotalDOF -CHARACTER(*), PARAMETER :: myName = "aField_GetTotalDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '// & - & ' child classes') -END PROCEDURE aField_GetTotalDOF - -!---------------------------------------------------------------------------- -! GetTotalVertexDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTotalVertexDOF -CHARACTER(*), PARAMETER :: myName = "aField_GetTotalVertexDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& - & 'child classes') -END PROCEDURE aField_GetTotalVertexDOF - -!---------------------------------------------------------------------------- -! GetTotalEdgeDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTotalEdgeDOF -CHARACTER(*), PARAMETER :: myName = "aField_GetTotalEdgeDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& - & 'child classes') -END PROCEDURE aField_GetTotalEdgeDOF - -!---------------------------------------------------------------------------- -! GetTotalFaceDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTotalFaceDOF -CHARACTER(*), PARAMETER :: myName = "aField_GetTotalFaceDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& - & 'child classes') -END PROCEDURE aField_GetTotalFaceDOF - -!---------------------------------------------------------------------------- -! GetTotalCellDOF -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_GetTotalCellDOF -CHARACTER(*), PARAMETER :: myName = "aField_GetTotalCellDOF()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[IMPLEMENTATION ERROR] :: This routine should be implemented by '//& - & 'child classes') -END PROCEDURE aField_GetTotalCellDOF - -!---------------------------------------------------------------------------- -! isConstant -!---------------------------------------------------------------------------- - -MODULE PROCEDURE aField_isConstant -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - ans = .TRUE. -ELSE - ans = .FALSE. -END IF -END PROCEDURE aField_isConstant - -END SUBMODULE Methods From b6bb1ad92fa8d4209eb7500821f9bb463b8bc018 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 17:52:49 +0900 Subject: [PATCH 046/117] Update AbstractNodeField - Adding AbstractNodeFieldInitiate1 - Adding AbstractNodeFieldInitiate2 - Adding AbstractNodeFieldCheckError --- .../src/AbstractNodeField_Class.F90 | 33 +++- ...ractNodeField_Class@ConstructorMethods.F90 | 175 +++++++++++++++--- 2 files changed, 180 insertions(+), 28 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index 2b57f74b5..0c7d58a65 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -169,13 +169,40 @@ END SUBROUTINE anf_SetParam ! date: 2023-09-22 ! summary: Initiate an instance of AbstractNodeField -INTERFACE - MODULE SUBROUTINE AbstractNodeFieldInitiate(obj, param, dom, prefix) +INTERFACE AbstractNodeFieldInitiate + MODULE SUBROUTINE AbstractNodeFieldInitiate1(obj, param, dom, prefix) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractNodeFieldInitiate + END SUBROUTINE AbstractNodeFieldInitiate1 +END INTERFACE AbstractNodeFieldInitiate + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Initiate an instance of AbstractNodeField + +INTERFACE AbstractNodeFieldInitiate + MODULE SUBROUTINE AbstractNodeFieldInitiate2(obj, param, dom, prefix) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) + CHARACTER(*), INTENT(IN) :: prefix + END SUBROUTINE AbstractNodeFieldInitiate2 +END INTERFACE AbstractNodeFieldInitiate + +!---------------------------------------------------------------------------- +! CheckError +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE AbstractNodeFieldCheckError(obj) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + END SUBROUTINE AbstractNodeFieldCheckError END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 index 60aa87958..1ecf39bc3 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 @@ -24,40 +24,72 @@ ! AbstractNodeFieldInitiate !---------------------------------------------------------------------------- -MODULE PROCEDURE AbstractNodeFieldInitiate -CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate()" +MODULE PROCEDURE AbstractNodeFieldInitiate1 +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate1()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractNodeFieldInitiate()') +#endif CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) -IF (obj%dof_tPhysicalVars .EQ. 0_I4B) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_tPhysicalVars is 0') -END IF +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'Calling AbstractNodeFieldCheckError()') +#endif -IF (.NOT. ALLOCATED(obj%dof_spaceCompo)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_spaceCompo '// & - & ' is NOT ALLOCATED') -END IF +CALL AbstractNodeFieldCheckError(obj) -IF (.NOT. ALLOCATED(obj%dof_timeCompo)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_timeCompo '// & - & ' is NOT ALLOCATED') -END IF +CALL Initiate( & + & obj=obj%dof, & + & tNodes=obj%dof_tNodes, & + & names=obj%dof_names_char, & + & spaceCompo=obj%dof_spaceCompo, & + & timeCompo=obj%dof_timeCompo, & + & storageFMT=obj%dof_storageFMT) -IF (.NOT. ALLOCATED(obj%dof_tNodes)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_tNodes '// & - & ' is NOT ALLOCATED') +CALL Initiate(obj=obj%realVec, dofobj=obj%dof) + +obj%tSize = SIZE(obj%realVec) + +IF (obj%local_n .EQ. 0) THEN + obj%local_n = obj%tSize END IF -IF (.NOT. ALLOCATED(obj%dof_names_char)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_names_char '// & - & ' is NOT ALLOCATED') +IF (obj%global_n .EQ. 0) THEN + obj%global_n = obj%tSize END IF +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractNodeFieldInitiate()') +#endif +END PROCEDURE AbstractNodeFieldInitiate1 + +!---------------------------------------------------------------------------- +! AbstractNodeFieldInitiate2 +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractNodeFieldInitiate2 +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate2()" +INTEGER(I4B) :: ivar, tvar +LOGICAL(LGT) :: isNOTOK + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractNodeFieldInitiate()') +#endif + +CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'Calling AbstractNodeFieldCheckError()') +#endif + +CALL AbstractNodeFieldCheckError(obj) + CALL Initiate( & & obj=obj%dof, & & tNodes=obj%dof_tNodes, & @@ -78,7 +110,100 @@ obj%global_n = obj%tSize END IF -END PROCEDURE AbstractNodeFieldInitiate +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractNodeFieldInitiate()') +#endif +END PROCEDURE AbstractNodeFieldInitiate2 + +!---------------------------------------------------------------------------- +! AbstractNodeFieldCheckError +!---------------------------------------------------------------------------- + +MODULE PROCEDURE AbstractNodeFieldCheckError +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldCheckError()" +INTEGER(I4B) :: ivar, tvar +LOGICAL(LGT) :: isNOTOK + +! CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) + +isNOTOK = obj%dof_tPhysicalVars .EQ. 0_I4B +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%dof_tPhysicalVars is 0') + RETURN +END IF + +isNOTOK = .NOT. ALLOCATED(obj%dof_spaceCompo) +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%dof_spaceCompo '// & + & ' is NOT ALLOCATED') + RETURN +END IF + +tvar = SIZE(obj%dof_spaceCompo) +isNOTOK = tvar .NE. obj%dof_tPhysicalVars +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: size of dof_spaceCompo ('//tostring(tvar)// & + & ') is not same as dof_tPhysicalVars ('// & + & tostring(obj%dof_tPhysicalVars)//')') + RETURN +END IF + +isNOTOK = .NOT. ALLOCATED(obj%dof_timeCompo) +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%dof_timeCompo '// & + & ' is NOT ALLOCATED') + RETURN +END IF + +tvar = SIZE(obj%dof_timeCompo) +isNOTOK = tvar .NE. obj%dof_tPhysicalVars +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: size of dof_timeCompo ('//tostring(tvar)// & + & ') is not same as dof_tPhysicalVars ('// & + & tostring(obj%dof_tPhysicalVars)//')') + RETURN +END IF + +IF (.NOT. ALLOCATED(obj%dof_tNodes)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%dof_tNodes '// & + & ' is NOT ALLOCATED') + RETURN +END IF + +tvar = SIZE(obj%dof_tNodes) +isNOTOK = tvar .NE. obj%dof_tPhysicalVars +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: size of dof_tNodes ('//tostring(tvar)// & + & ') is not same as dof_tPhysicalVars ('// & + & tostring(obj%dof_tPhysicalVars)//')') + RETURN +END IF + +IF (.NOT. ALLOCATED(obj%dof_names_char)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[InitIATE ERROR] :: AbstractNodeField_::obj%dof_names_char '// & + & ' is NOT ALLOCATED') + RETURN +END IF + +tvar = SIZE(obj%dof_names_char) +isNOTOK = tvar .NE. obj%dof_tPhysicalVars +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: size of dof_names_char ('//tostring(tvar)// & + & ') is not same as dof_tPhysicalVars ('// & + & tostring(obj%dof_tPhysicalVars)//')') + RETURN +END IF +END PROCEDURE AbstractNodeFieldCheckError !---------------------------------------------------------------------------- ! Initiate2 From 09cc87045adebe2b488226ee830de4c76a97d447 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 17:53:34 +0900 Subject: [PATCH 047/117] Update in STVectorField - Minor updates in STVectorField_Class --- .../STVectorField/src/STVectorField_Class.F90 | 10 +++++++-- ...STVectorField_Class@ConstructorMethods.F90 | 22 ++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/modules/STVectorField/src/STVectorField_Class.F90 b/src/modules/STVectorField/src/STVectorField_Class.F90 index b457a984c..ba2858a6f 100644 --- a/src/modules/STVectorField/src/STVectorField_Class.F90 +++ b/src/modules/STVectorField/src/STVectorField_Class.F90 @@ -33,6 +33,9 @@ MODULE STVectorField_Class PRIVATE CHARACTER(*), PARAMETER :: modName = "STVectorField_Class" CHARACTER(*), PARAMETER :: myprefix = "STVectorField" + +PUBLIC :: STVectorField_ +PUBLIC :: TypeSTVectorField PUBLIC :: STVectorFieldPointer_ PUBLIC :: SetSTVectorFieldParam PUBLIC :: STVectorFieldInitiate1 @@ -140,8 +143,11 @@ MODULE STVectorField_Class & stvField_ApplyDirichletBC2 END TYPE STVectorField_ -PUBLIC :: STVectorField_ -TYPE(STVectorField_), PARAMETER, PUBLIC :: TypeSTVectorField = & +!---------------------------------------------------------------------------- +! TypeSTVectorField +!---------------------------------------------------------------------------- + +TYPE(STVectorField_), PARAMETER :: TypeSTVectorField = & & STVectorField_(domains=NULL()) !--------------------------------------------------------------------------- diff --git a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 index a9557f2e8..6dc555141 100644 --- a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 @@ -52,18 +52,10 @@ & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') END IF -CALL Set( & - & obj=sublist, & - & datatype=TypeIntI4B, & - & prefix=myprefix, & - & key="spaceCompo", & +CALL Set(obj=sublist, datatype=1_I4B, prefix=myprefix, key="spaceCompo", & & VALUE=spaceCompo) -CALL Set( & - & obj=sublist, & - & datatype=TypeIntI4B, & - & prefix=myprefix, & - & key="timeCompo", & +CALL Set(obj=sublist, datatype=1_I4B, prefix=myprefix, key="timeCompo", & & VALUE=timeCompo) sublist => NULL() @@ -98,6 +90,11 @@ INTEGER(I4B) :: nsd, tdof, ierr, tNodes TYPE(ParameterList_), POINTER :: sublist +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + ! main sublist => NULL() @@ -146,6 +143,11 @@ astr = "" sublist => NULL() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif END PROCEDURE stvField_Initiate1 !---------------------------------------------------------------------------- From 14bcad8d22b3f04757c9a0e23b75dfad6c69ea89 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 17:54:25 +0900 Subject: [PATCH 048/117] Update in BlockNodeField - Adding GetFEVariable method - Adding vtk export support - Minor formatting --- .../src/BlockNodeField_Class.F90 | 361 +++++++++--------- ...lockNodeField_Class@ConstructorMethods.F90 | 342 ++++++++++------- .../src/BlockNodeField_Class@GetMethods.F90 | 73 ++-- 3 files changed, 427 insertions(+), 349 deletions(-) diff --git a/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 b/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 index 9f07306ef..2d313db54 100644 --- a/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 +++ b/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 @@ -20,7 +20,7 @@ MODULE BlockNodeField_Class USE GlobalData -USE BaseType +USE BaSetype USE String_Class USE AbstractField_Class USE AbstractNodeField_Class @@ -33,6 +33,12 @@ MODULE BlockNodeField_Class PRIVATE CHARACTER(*), PARAMETER :: modName = "BlockNodeField_Class" CHARACTER(*), PARAMETER :: myprefix = "BlockNodeField" +PUBLIC :: BlockNodeFieldPointer_ +PUBLIC :: BlockNodeField_ +PUBLIC :: TypeBlockNodeField +PUBLIC :: SetBlockNodeFieldParam +PUBLIC :: BlockNodeFieldInitiate1 +PUBLIC :: BlockNodeFieldInitiate3 !---------------------------------------------------------------------------- ! BlockNodeField_ @@ -47,77 +53,84 @@ MODULE BlockNodeField_Class TYPE, EXTENDS(AbstractNodeField_) :: BlockNodeField_ CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethod PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & & bnField_checkEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => bnField_Initiate1 PROCEDURE, PUBLIC, PASS(obj) :: Initiate3 => bnField_Initiate3 FINAL :: bnField_Final - ! + + ! IO: ! @IOMethods - ! PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => bnField_Import - ! + + ! SET: ! @SetMethods - ! - PROCEDURE, PASS(obj) :: set1 => bnField_set1 - !! set single entry - PROCEDURE, PASS(obj) :: set2 => bnField_set2 - !! set all values to a scalar values - PROCEDURE, PASS(obj) :: ASSIGN => bnField_assign - !! set all values to a scalar values + PROCEDURE, PASS(obj) :: Set1 => bnField_Set1 + !! Set single entry + PROCEDURE, PASS(obj) :: Set2 => bnField_Set2 + !! Set all values to a scalar values + PROCEDURE, PASS(obj) :: ASSIGN => bnField_Assign + !! Set all values to a scalar values GENERIC, PUBLIC :: ASSIGNMENT(=) => ASSIGN - !! Assignment, obj = scalar - PROCEDURE, PASS(obj) :: set3 => bnField_set3 - !! set all values to a given vector - PROCEDURE, PASS(obj) :: set4 => bnField_set4 - !! set selected values to given scalar - PROCEDURE, PASS(obj) :: set5 => bnField_set5 - PROCEDURE, PASS(obj) :: set6 => bnField_set6 - PROCEDURE, PASS(obj) :: set7 => bnField_set7 - PROCEDURE, PASS(obj) :: set8 => bnField_set8 - PROCEDURE, PASS(obj) :: set9 => bnField_set9 - PROCEDURE, PASS(obj) :: set10 => bnField_set10 - PROCEDURE, PASS(obj) :: set11 => bnField_set11 - PROCEDURE, PASS(obj) :: set12 => bnField_set12 - PROCEDURE, PASS(obj) :: set13 => bnField_set13 - PROCEDURE, PASS(obj) :: set14 => bnField_set14 - PROCEDURE, PASS(obj) :: set15 => bnField_set15 - PROCEDURE, PASS(obj) :: set16 => bnField_set16 - PROCEDURE, PASS(obj) :: set17 => bnField_set17 - PROCEDURE, PASS(obj) :: set18 => bnField_set18 - GENERIC, PUBLIC :: set => set1, set2, set3, set4, & - & set5, set6, set7, set8, set9, set10, set11, & - & set12, set13, set14, set15, set16, set17, set18 - ! + !! Assignment, obj = scalar + PROCEDURE, PASS(obj) :: Set3 => bnField_Set3 + !! Set all values to a given vector + PROCEDURE, PASS(obj) :: Set4 => bnField_Set4 + !! Set selected values to given scalar + PROCEDURE, PASS(obj) :: Set5 => bnField_Set5 + PROCEDURE, PASS(obj) :: Set6 => bnField_Set6 + PROCEDURE, PASS(obj) :: Set7 => bnField_Set7 + PROCEDURE, PASS(obj) :: Set8 => bnField_Set8 + PROCEDURE, PASS(obj) :: Set9 => bnField_Set9 + PROCEDURE, PASS(obj) :: Set10 => bnField_Set10 + PROCEDURE, PASS(obj) :: Set11 => bnField_Set11 + PROCEDURE, PASS(obj) :: Set12 => bnField_Set12 + PROCEDURE, PASS(obj) :: Set13 => bnField_Set13 + PROCEDURE, PASS(obj) :: Set14 => bnField_Set14 + PROCEDURE, PASS(obj) :: Set15 => bnField_Set15 + PROCEDURE, PASS(obj) :: Set16 => bnField_Set16 + PROCEDURE, PASS(obj) :: Set17 => bnField_Set17 + PROCEDURE, PASS(obj) :: Set18 => bnField_Set18 + GENERIC, PUBLIC :: Set => Set1, Set2, Set3, Set4, & + & Set5, Set6, Set7, Set8, Set9, Set10, Set11, & + & Set12, Set13, Set14, Set15, Set16, Set17, Set18 + + ! GET: ! @GetMethods - ! - PROCEDURE, PASS(obj) :: get1 => bnField_get1 - PROCEDURE, PASS(obj) :: get2 => bnField_get2 - PROCEDURE, PASS(obj) :: get3 => bnField_get3 - PROCEDURE, PASS(obj) :: get4 => bnField_get4 - PROCEDURE, PASS(obj) :: get5 => bnField_get5 - PROCEDURE, PASS(obj) :: get6 => bnField_get6 - PROCEDURE, PASS(obj) :: get7 => bnField_get7 - PROCEDURE, PASS(obj) :: get8 => bnField_get8 - PROCEDURE, PASS(obj) :: get9 => bnField_get9 - GENERIC, PUBLIC :: get => get1, get2, get3, get4, & - & get5, get6, get7, get8, get9 - - PROCEDURE, PASS(obj) :: bnField_applyDirichletBC1 - PROCEDURE, PASS(obj) :: bnField_applyDirichletBC2 - GENERIC, PUBLIC :: applyDirichletBC => & - & bnField_applyDirichletBC1, & - & bnField_applyDirichletBC2 - ! - ! @Operator - ! - PROCEDURE, PASS(obj) :: isEqual => bnField_isEqual - GENERIC, PUBLIC :: OPERATOR(.EQ.) => isEqual + PROCEDURE, PASS(obj) :: Get1 => bnField_Get1 + PROCEDURE, PASS(obj) :: Get2 => bnField_Get2 + PROCEDURE, PASS(obj) :: Get3 => bnField_Get3 + PROCEDURE, PASS(obj) :: Get4 => bnField_Get4 + PROCEDURE, PASS(obj) :: Get5 => bnField_Get5 + PROCEDURE, PASS(obj) :: Get6 => bnField_Get6 + PROCEDURE, PASS(obj) :: Get7 => bnField_Get7 + PROCEDURE, PASS(obj) :: Get8 => bnField_Get8 + PROCEDURE, PASS(obj) :: Get9 => bnField_Get9 + GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, & + & Get5, Get6, Get7, Get8, Get9 + PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => bnField_GetFEVariable + + ! SET: + ! @DirichletBCMethods + PROCEDURE, PASS(obj) :: bnField_ApplyDirichletBC1 + PROCEDURE, PASS(obj) :: bnField_ApplyDirichletBC2 + GENERIC, PUBLIC :: ApplyDirichletBC => bnField_ApplyDirichletBC1, & + & bnField_ApplyDirichletBC2 + + ! GET: + ! @OperatorMethods + PROCEDURE, PASS(obj) :: IsEqual => bnField_IsEqual + GENERIC, PUBLIC :: OPERATOR(.EQ.) => IsEqual END TYPE BlockNodeField_ -PUBLIC :: BlockNodeField_ +!---------------------------------------------------------------------------- +! TypeBlockNodeField +!---------------------------------------------------------------------------- -TYPE(BlockNodeField_), PARAMETER, PUBLIC :: TypeBlockNodeField = & +TYPE(BlockNodeField_), PARAMETER :: TypeBlockNodeField = & & BlockNodeField_(domains=NULL()) !---------------------------------------------------------------------------- @@ -128,10 +141,8 @@ MODULE BlockNodeField_Class CLASS(BlockNodeField_), POINTER :: ptr => NULL() END TYPE BlockNodeFieldPointer_ -PUBLIC :: BlockNodeFieldPointer_ - !---------------------------------------------------------------------------- -! setBlockNodeFieldParam@ConstructorMethod +! SetBlockNodeFieldParam@ConstructorMethod !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -177,8 +188,6 @@ MODULE SUBROUTINE SetBlockNodeFieldParam(param, & END SUBROUTINE SetBlockNodeFieldParam END INTERFACE -PUBLIC :: SetBlockNodeFieldParam - !---------------------------------------------------------------------------- ! checkEssentialParam@ConstructorMethod !---------------------------------------------------------------------------- @@ -213,23 +222,22 @@ END SUBROUTINE bnField_checkEssentialParam ! !@note ! `param` should be constructed by calling -! [[BlockNodeField_Class::setBloclNodeFieldParam]] routine. +! [[BlockNodeField_Class::SetBloclNodeFieldParam]] routine. +!@endnote +! +!!@note +! This routine calls [[BlockNodeField_Class::BlockNodeFieldInitiate3]] +! routine. !@endnote -INTERFACE +INTERFACE BlockNodeFieldInitiate1 MODULE SUBROUTINE bnField_Initiate1(obj, param, dom) CLASS(BlockNodeField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom END SUBROUTINE bnField_Initiate1 -END INTERFACE - -INTERFACE BlockNodeFieldInitiate1 - MODULE PROCEDURE bnField_Initiate1 END INTERFACE BlockNodeFieldInitiate1 -PUBLIC :: BlockNodeFieldInitiate1 - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethod !---------------------------------------------------------------------------- @@ -245,25 +253,19 @@ END SUBROUTINE bnField_Initiate1 ! instance of BlockNodeField_ . ! ! - It is better to make `param` by calling -! [[BlockNodeField_::setBlockNodeFieldParam]] +! [[BlockNodeField_::SetBlockNodeFieldParam]] ! - The size of `dom` should be equal to the number of physical variables ! present in the block node field. ! - `dom` contains the pointer to [[Domain_]] class. -INTERFACE +INTERFACE BlockNodeFieldInitiate3 MODULE SUBROUTINE bnField_Initiate3(obj, param, dom) CLASS(BlockNodeField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) END SUBROUTINE bnField_Initiate3 -END INTERFACE - -INTERFACE BlockNodeFieldInitiate3 - MODULE PROCEDURE bnField_Initiate3 END INTERFACE BlockNodeFieldInitiate3 -PUBLIC :: BlockNodeFieldInitiate3 - !---------------------------------------------------------------------------- ! Final@ConstructorMethod !---------------------------------------------------------------------------- @@ -298,15 +300,15 @@ END SUBROUTINE bnField_Import !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets all values to a scalar +! summary: This routine Sets all values to a scalar INTERFACE - MODULE SUBROUTINE bnField_set1(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE bnField_Set1(obj, VALUE, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set1 + END SUBROUTINE bnField_Set1 END INTERFACE !---------------------------------------------------------------------------- @@ -315,15 +317,15 @@ END SUBROUTINE bnField_set1 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets all values to val +! summary: This routine Sets all values to val INTERFACE - MODULE SUBROUTINE bnField_set2(obj, VALUE, scale, addContribution) + MODULE SUBROUTINE bnField_Set2(obj, VALUE, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set2 + END SUBROUTINE bnField_Set2 END INTERFACE !---------------------------------------------------------------------------- @@ -332,10 +334,10 @@ END SUBROUTINE bnField_set2 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the single value +! summary: This routine Sets the single value INTERFACE - MODULE SUBROUTINE bnField_set3(obj, globalNode, VALUE, ivar, idof, & + MODULE SUBROUTINE bnField_Set3(obj, globalNode, VALUE, ivar, idof, & & scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode @@ -344,7 +346,7 @@ MODULE SUBROUTINE bnField_set3(obj, globalNode, VALUE, ivar, idof, & INTEGER(I4B), INTENT(IN) :: idof REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set3 + END SUBROUTINE bnField_Set3 END INTERFACE !---------------------------------------------------------------------------- @@ -353,10 +355,10 @@ END SUBROUTINE bnField_set3 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets selected values to a scalar value +! summary: This routine Sets selected values to a scalar value INTERFACE - MODULE SUBROUTINE bnField_set4(obj, globalNode, VALUE, ivar, scale, & + MODULE SUBROUTINE bnField_Set4(obj, globalNode, VALUE, ivar, scale, & & addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -364,7 +366,7 @@ MODULE SUBROUTINE bnField_set4(obj, globalNode, VALUE, ivar, scale, & INTEGER(I4B), INTENT(IN) :: ivar REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set4 + END SUBROUTINE bnField_Set4 END INTERFACE !---------------------------------------------------------------------------- @@ -373,10 +375,10 @@ END SUBROUTINE bnField_set4 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets selected values to a scalar value +! summary: This routine Sets selected values to a scalar value INTERFACE - MODULE SUBROUTINE bnField_set5(obj, globalNode, VALUE, ivar, scale, & + MODULE SUBROUTINE bnField_Set5(obj, globalNode, VALUE, ivar, scale, & & addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -384,7 +386,7 @@ MODULE SUBROUTINE bnField_set5(obj, globalNode, VALUE, ivar, scale, & INTEGER(I4B), INTENT(IN) :: ivar REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set5 + END SUBROUTINE bnField_Set5 END INTERFACE !---------------------------------------------------------------------------- @@ -393,10 +395,10 @@ END SUBROUTINE bnField_set5 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set6(obj, globalNode, VALUE, ivar, idof, & + MODULE SUBROUTINE bnField_Set6(obj, globalNode, VALUE, ivar, idof, & & scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -405,7 +407,7 @@ MODULE SUBROUTINE bnField_set6(obj, globalNode, VALUE, ivar, idof, & INTEGER(I4B), INTENT(IN) :: idof REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set6 + END SUBROUTINE bnField_Set6 END INTERFACE !---------------------------------------------------------------------------- @@ -414,10 +416,10 @@ END SUBROUTINE bnField_set6 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set7(obj, globalNode, VALUE, ivar, idof, & + MODULE SUBROUTINE bnField_Set7(obj, globalNode, VALUE, ivar, idof, & & scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -426,7 +428,7 @@ MODULE SUBROUTINE bnField_set7(obj, globalNode, VALUE, ivar, idof, & INTEGER(I4B), INTENT(IN) :: idof REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set7 + END SUBROUTINE bnField_Set7 END INTERFACE !---------------------------------------------------------------------------- @@ -435,10 +437,10 @@ END SUBROUTINE bnField_set7 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set8(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set8(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -448,7 +450,7 @@ MODULE SUBROUTINE bnField_set8(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set8 + END SUBROUTINE bnField_Set8 END INTERFACE !---------------------------------------------------------------------------- @@ -457,10 +459,10 @@ END SUBROUTINE bnField_set8 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set9(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set9(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -470,7 +472,7 @@ MODULE SUBROUTINE bnField_set9(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set9 + END SUBROUTINE bnField_Set9 END INTERFACE !---------------------------------------------------------------------------- @@ -479,10 +481,10 @@ END SUBROUTINE bnField_set9 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set10(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set10(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -492,7 +494,7 @@ MODULE SUBROUTINE bnField_set10(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set10 + END SUBROUTINE bnField_Set10 END INTERFACE !---------------------------------------------------------------------------- @@ -501,10 +503,10 @@ END SUBROUTINE bnField_set10 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set11(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set11(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -514,7 +516,7 @@ MODULE SUBROUTINE bnField_set11(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set11 + END SUBROUTINE bnField_Set11 END INTERFACE !---------------------------------------------------------------------------- @@ -523,10 +525,10 @@ END SUBROUTINE bnField_set11 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set12(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set12(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -536,7 +538,7 @@ MODULE SUBROUTINE bnField_set12(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set12 + END SUBROUTINE bnField_Set12 END INTERFACE !---------------------------------------------------------------------------- @@ -545,10 +547,10 @@ END SUBROUTINE bnField_set12 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set13(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set13(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode(:) @@ -558,7 +560,7 @@ MODULE SUBROUTINE bnField_set13(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set13 + END SUBROUTINE bnField_Set13 END INTERFACE !---------------------------------------------------------------------------- @@ -567,10 +569,10 @@ END SUBROUTINE bnField_set13 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set14(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set14(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode @@ -580,7 +582,7 @@ MODULE SUBROUTINE bnField_set14(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set14 + END SUBROUTINE bnField_Set14 END INTERFACE !---------------------------------------------------------------------------- @@ -589,10 +591,10 @@ END SUBROUTINE bnField_set14 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set15(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set15(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode @@ -602,7 +604,7 @@ MODULE SUBROUTINE bnField_set15(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo(:) REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set15 + END SUBROUTINE bnField_Set15 END INTERFACE !---------------------------------------------------------------------------- @@ -611,10 +613,10 @@ END SUBROUTINE bnField_set15 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected values +! summary: This routine Sets the selected values INTERFACE - MODULE SUBROUTINE bnField_set16(obj, globalNode, VALUE, ivar, & + MODULE SUBROUTINE bnField_Set16(obj, globalNode, VALUE, ivar, & & spaceCompo, timeCompo, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: globalNode @@ -624,7 +626,7 @@ MODULE SUBROUTINE bnField_set16(obj, globalNode, VALUE, ivar, & INTEGER(I4B), INTENT(IN) :: timeCompo REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set16 + END SUBROUTINE bnField_Set16 END INTERFACE !---------------------------------------------------------------------------- @@ -633,15 +635,15 @@ END SUBROUTINE bnField_set16 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets the selected entries +! summary: This routine Sets the selected entries INTERFACE - MODULE SUBROUTINE bnField_set17(obj, obj2, scale, addContribution) + MODULE SUBROUTINE bnField_Set17(obj, obj2, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj CLASS(BlockNodeField_), INTENT(IN) :: obj2 REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set17 + END SUBROUTINE bnField_Set17 END INTERFACE !---------------------------------------------------------------------------- @@ -653,7 +655,7 @@ END SUBROUTINE bnField_set17 ! summary: Setvalues INTERFACE - MODULE SUBROUTINE bnField_set18(obj, ivar, idof, VALUE, ivar_value, & + MODULE SUBROUTINE bnField_Set18(obj, ivar, idof, VALUE, ivar_value, & & idof_value, scale, addContribution) CLASS(BlockNodeField_), INTENT(INOUT) :: obj INTEGER(I4B), INTENT(IN) :: ivar @@ -663,7 +665,7 @@ MODULE SUBROUTINE bnField_set18(obj, ivar, idof, VALUE, ivar_value, & INTEGER(I4B), INTENT(IN) :: idof_value REAL(DFP), OPTIONAL, INTENT(IN) :: scale LOGICAL(LGT), OPTIONAL, INTENT(IN) :: addContribution - END SUBROUTINE bnField_set18 + END SUBROUTINE bnField_Set18 END INTERFACE !---------------------------------------------------------------------------- @@ -672,17 +674,17 @@ END SUBROUTINE bnField_set18 !> authors: Vikas Sharma, Ph. D. ! date: 06 Jan 2022 -! summary: This routine sets all values to a scalar +! summary: This routine Sets all values to a scalar INTERFACE - MODULE SUBROUTINE bnField_assign(obj, VALUE) + MODULE SUBROUTINE bnField_Assign(obj, VALUE) CLASS(BlockNodeField_), INTENT(INOUT) :: obj REAL(DFP), INTENT(IN) :: VALUE - END SUBROUTINE bnField_assign + END SUBROUTINE bnField_Assign END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -690,7 +692,7 @@ END SUBROUTINE bnField_assign ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get1(obj, VALUE, globalNode, ivar, idof) + MODULE SUBROUTINE bnField_Get1(obj, VALUE, globalNode, ivar, idof) CLASS(BlockNodeField_), INTENT(IN) :: obj REAL(DFP), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: globalNode @@ -698,11 +700,11 @@ MODULE SUBROUTINE bnField_get1(obj, VALUE, globalNode, ivar, idof) !! physical variable number INTEGER(I4B), INTENT(IN) :: idof !! degree of freedom number - END SUBROUTINE bnField_get1 + END SUBROUTINE bnField_Get1 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -710,14 +712,14 @@ END SUBROUTINE bnField_get1 ! summary: returns all the values INTERFACE - MODULE SUBROUTINE bnField_get2(obj, VALUE) + MODULE SUBROUTINE bnField_Get2(obj, VALUE) CLASS(BlockNodeField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) - END SUBROUTINE bnField_get2 + END SUBROUTINE bnField_Get2 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -725,17 +727,17 @@ END SUBROUTINE bnField_get2 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get3(obj, VALUE, globalNode, ivar, idof) + MODULE SUBROUTINE bnField_Get3(obj, VALUE, globalNode, ivar, idof) CLASS(BlockNodeField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof - END SUBROUTINE bnField_get3 + END SUBROUTINE bnField_Get3 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -743,7 +745,7 @@ END SUBROUTINE bnField_get3 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get4(obj, VALUE, istart, iend, stride, & + MODULE SUBROUTINE bnField_Get4(obj, VALUE, istart, iend, stride, & & ivar, idof) CLASS(BlockNodeField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) @@ -752,11 +754,11 @@ MODULE SUBROUTINE bnField_get4(obj, VALUE, istart, iend, stride, & INTEGER(I4B), INTENT(IN) :: stride INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof - END SUBROUTINE bnField_get4 + END SUBROUTINE bnField_Get4 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -764,7 +766,7 @@ END SUBROUTINE bnField_get4 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get5(obj, VALUE, globalNode, & + MODULE SUBROUTINE bnField_Get5(obj, VALUE, globalNode, & & ivar, idof) CLASS(BlockNodeField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE @@ -774,11 +776,11 @@ MODULE SUBROUTINE bnField_get5(obj, VALUE, globalNode, & INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof - END SUBROUTINE bnField_get5 + END SUBROUTINE bnField_Get5 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -786,7 +788,7 @@ END SUBROUTINE bnField_get5 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get6(obj, VALUE, globalNode, ivar) + MODULE SUBROUTINE bnField_Get6(obj, VALUE, globalNode, ivar) CLASS(BlockNodeField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE !! NodalVariable @@ -796,11 +798,11 @@ MODULE SUBROUTINE bnField_get6(obj, VALUE, globalNode, ivar) !! If timeCompo is greater than 1, then FETypeSpaceTime INTEGER(I4B), INTENT(IN) :: globalNode(:) INTEGER(I4B), INTENT(IN) :: ivar - END SUBROUTINE bnField_get6 + END SUBROUTINE bnField_Get6 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -808,7 +810,7 @@ END SUBROUTINE bnField_get6 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get7(obj, VALUE, globalNode, ivar, & + MODULE SUBROUTINE bnField_Get7(obj, VALUE, globalNode, ivar, & & spaceCompo, timeCompo) CLASS(BlockNodeField_), INTENT(IN) :: obj REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: VALUE(:) @@ -816,11 +818,11 @@ MODULE SUBROUTINE bnField_get7(obj, VALUE, globalNode, ivar, & INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE bnField_get7 + END SUBROUTINE bnField_Get7 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -828,7 +830,7 @@ END SUBROUTINE bnField_get7 ! summary: This routine returns the single entry of the scalar field INTERFACE - MODULE SUBROUTINE bnField_get8(obj, VALUE, globalNode, ivar, & + MODULE SUBROUTINE bnField_Get8(obj, VALUE, globalNode, ivar, & & spaceCompo, timeCompo) CLASS(BlockNodeField_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: VALUE @@ -839,11 +841,11 @@ MODULE SUBROUTINE bnField_get8(obj, VALUE, globalNode, ivar, & INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: spaceCompo INTEGER(I4B), INTENT(IN) :: timeCompo - END SUBROUTINE bnField_get8 + END SUBROUTINE bnField_Get8 END INTERFACE !---------------------------------------------------------------------------- -! get@GetMethods +! Get@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -851,18 +853,35 @@ END SUBROUTINE bnField_get8 ! summary: Returns values INTERFACE -MODULE SUBROUTINE bnField_get9(obj, ivar, idof, VALUE, ivar_value, idof_value) +MODULE SUBROUTINE bnField_Get9(obj, ivar, idof, VALUE, ivar_value, idof_value) CLASS(BlockNodeField_), INTENT(IN) :: obj CLASS(AbstractNodeField_), INTENT(INOUT) :: VALUE INTEGER(I4B), INTENT(IN) :: ivar INTEGER(I4B), INTENT(IN) :: idof INTEGER(I4B), INTENT(IN) :: ivar_value INTEGER(I4B), INTENT(IN) :: idof_value - END SUBROUTINE bnField_get9 + END SUBROUTINE bnField_Get9 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! GetFEVariable@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-03-28 +! summary: Set single entry + +INTERFACE BlockFieldGetFEVariable + MODULE SUBROUTINE bnField_GetFeVariable(obj, globalNode, VALUE, ivar) + CLASS(BlockNodeField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + TYPE(FEVariable_), INTENT(INOUT) :: VALUE + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END SUBROUTINE bnField_GetFeVariable +END INTERFACE BlockFieldGetFEVariable + +!---------------------------------------------------------------------------- +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -870,15 +889,15 @@ END SUBROUTINE bnField_get9 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE bnField_applyDirichletBC1(obj, dbc, ivar) + MODULE SUBROUTINE bnField_ApplyDirichletBC1(obj, dbc, ivar) CLASS(BlockNodeField_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc INTEGER(I4B), INTENT(IN) :: ivar - END SUBROUTINE bnField_applyDirichletBC1 + END SUBROUTINE bnField_ApplyDirichletBC1 END INTERFACE !---------------------------------------------------------------------------- -! applyDirichletBC@DBCMethods +! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -886,11 +905,11 @@ END SUBROUTINE bnField_applyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE bnField_applyDirichletBC2(obj, dbc, ivar) + MODULE SUBROUTINE bnField_ApplyDirichletBC2(obj, dbc, ivar) CLASS(BlockNodeField_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) INTEGER(I4B), INTENT(IN) :: ivar - END SUBROUTINE bnField_applyDirichletBC2 + END SUBROUTINE bnField_ApplyDirichletBC2 END INTERFACE !---------------------------------------------------------------------------- @@ -898,11 +917,11 @@ END SUBROUTINE bnField_applyDirichletBC2 !---------------------------------------------------------------------------- INTERFACE - MODULE FUNCTION bnField_isEqual(obj, obj2) RESULT(Ans) + MODULE FUNCTION bnField_IsEqual(obj, obj2) RESULT(Ans) CLASS(BlockNodeField_), INTENT(IN) :: obj CLASS(BlockNodeField_), INTENT(IN) :: obj2 LOGICAL(LGT) :: ans - END FUNCTION bnField_isEqual + END FUNCTION bnField_IsEqual END INTERFACE !---------------------------------------------------------------------------- diff --git a/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 b/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 index e9a081ee9..0b2b92eca 100644 --- a/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 @@ -16,6 +16,7 @@ SUBMODULE(BlockNodeField_Class) ConstructorMethods USE BaseMethod +USE FPL_Method IMPLICIT NONE CONTAINS @@ -24,109 +25,155 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE SetBlockNodeFieldParam -CHARACTER(*), PARAMETER :: myName = "SetBlockNodeFieldParam" -INTEGER(I4B) :: ierr0, ii -IF (ANY([SIZE(physicalVarNames), SIZE(spaceCompo), SIZE(timeCompo)] & - & .NE. SIZE(physicalVarNames))) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Size of physicalVarNames, spaceCompo, and timeCompo should be & - & same') +CHARACTER(*), PARAMETER :: myName = "SetBlockNodeFieldParam()" +INTEGER(I4B) :: ierr, ii, intvec(3) +LOGICAL(LGT) :: isNOTOK +TYPE(ParameterList_), POINTER :: sublist + +intvec = [SIZE(physicalVarNames), SIZE(spaceCompo), SIZE(timeCompo)] +isNOTOK = ANY(intvec .NE. SIZE(physicalVarNames)) + +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: Size of physicalVarNames, spaceCompo, '// & + & 'and timeCompo should be same.') + RETURN END IF -ierr0 = param%set(key=myprefix//"/name", VALUE=TRIM(name)) -ierr0 = param%set(key=myprefix//"/engine", VALUE=TRIM(engine)) -ii = SIZE(physicalVarNames) -ierr0 = param%set(key=myprefix//"/tPhysicalVarNames", VALUE=ii) + +CALL SetAbstractFieldParam( & + & param=param, & + & prefix=myprefix, & + & name=name, & + & engine=engine, & + & fieldType=fieldType, & + & comm=comm, & + & local_n=local_n, & + & global_n=global_n) + +sublist => NULL() +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in Getting sublist(1)') + RETURN +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in Getting sublist(2)') +END IF + +CALL Set(obj=sublist, datatype=1_I4B, prefix=myprefix, & + & key="tPhysicalVarNames", VALUE=intvec(1)) + DO ii = 1, SIZE(physicalVarNames) - ierr0 = param%set(key=myprefix//"/physicalVarName"//TOSTRING(ii), & - & VALUE=physicalVarNames(ii)) + CALL Set(obj=sublist, datatype="char", prefix=myprefix, & + & key="physicalVarName"//tostring(ii), VALUE=physicalVarNames(ii)) END DO -ierr0 = param%set(key=myprefix//"/spaceCompo", & - & VALUE=spaceCompo) -ierr0 = param%set(key=myprefix//"/timeCompo", & + +CALL Set(obj=sublist, datatype=[1_I4B], prefix=myprefix, key="spaceCompo", & + & VALUE=spaceCompo) + +CALL Set(obj=sublist, datatype=[1_I4B], prefix=myprefix, key="timeCompo", & & VALUE=timeCompo) -ierr0 = param%set(key=myprefix//"/fieldType", VALUE=INPUT( & - & option=fieldType, default=FIELD_TYPE_NORMAL)) -IF (PRESENT(comm)) THEN - ierr0 = param%set(key=myprefix//"/comm", VALUE=comm) -ELSE - ierr0 = param%set(key=myprefix//"/comm", VALUE=0_I4B) -END IF -IF (PRESENT(local_n)) THEN - ierr0 = param%set(key=myprefix//"/local_n", VALUE=local_n) -ELSE - ierr0 = param%set(key=myprefix//"/local_n", VALUE=0_I4B) -END IF -IF (PRESENT(global_n)) THEN - ierr0 = param%set(key=myprefix//"/global_n", VALUE=global_n) -ELSE - ierr0 = param%set(key=myprefix//"/global_n", VALUE=0_I4B) -END IF + +sublist => NULL() END PROCEDURE SetBlockNodeFieldParam !---------------------------------------------------------------------------- -! checkEssentialParam +! CheckEssentialParam !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_checkEssentialParam -CHARACTER(*), PARAMETER :: myName = "bnField_checkEssentialParam" +MODULE PROCEDURE bnField_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "bnField_CheckEssentialParam" INTEGER(I4B) :: ii, n -IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/name should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/engine")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/engine should be present in param') -END IF -IF (.NOT. param%isPresent(key=myprefix//"/tPhysicalVarNames")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/tPhysicalVarNames should be present in param') -ELSE - ii = param%get(key=myprefix//'/tPhysicalVarNames', VALUE=n) -END IF -IF (.NOT. param%isPresent(key=myprefix//"/spaceCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & +CALL AbstractFieldCheckEssentialParam(obj=obj, param=param, prefix=myprefix) + +IF (.NOT. param%IsPresent(key=myprefix//"/spaceCompo")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & & myprefix//'/spaceCompo should be present in param') + RETURN END IF -IF (.NOT. param%isPresent(key=myprefix//"/timeCompo")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + +IF (.NOT. param%IsPresent(key=myprefix//"/timeCompo")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & & myprefix//'/timeCompo should be present in param') + RETURN END IF -IF (.NOT. param%isPresent(key=myprefix//"/fieldType")) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/fieldType should be present in param') + +n = 0 +IF (.NOT. param%IsPresent(key=myprefix//"/tPhysicalVarNames")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/tPhysicalVarNames should be present in param') + RETURN +ELSE + ii = param%Get(key=myprefix//'/tPhysicalVarNames', VALUE=n) END IF + DO ii = 1, n - IF (.NOT. param%isPresent(key=myprefix//"/physicalVarName" & + IF (.NOT. param%IsPresent(key=myprefix//"/physicalVarName" & & //TOSTRING(ii))) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & myprefix//'/physicalVarName' & - & //TOSTRING(ii) & + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/physicalVarName'//TOSTRING(ii) & & //' should be present in param') END IF END DO -END PROCEDURE bnField_checkEssentialParam + +END PROCEDURE bnField_CheckEssentialParam !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- MODULE PROCEDURE bnField_Initiate1 -CHARACTER(*), PARAMETER :: myName = "bnField_Initiate1" +CHARACTER(*), PARAMETER :: myName = "bnField_Initiate1()" TYPE(DomainPointer_), ALLOCATABLE :: domains(:) -INTEGER(I4B) :: tPhysicalVarNames, ii -ii = param%get(key=myprefix//"/tPhysicalVarNames", & +INTEGER(I4B) :: tPhysicalVarNames, ii, ierr +TYPE(ParameterList_), POINTER :: sublist + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +! main +sublist => NULL() + +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + RETURN +END IF + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') + RETURN +END IF + +CALL GetValue(obj=sublist, prefix=myprefix, key="tPhysicalVarNames", & & VALUE=tPhysicalVarNames) + ALLOCATE (domains(tPhysicalVarNames)) DO ii = 1, tPhysicalVarNames domains(ii)%ptr => dom END DO + CALL obj%Initiate(param=param, dom=domains) + DO ii = 1, tPhysicalVarNames domains(ii)%ptr => NULL() END DO DEALLOCATE (domains) + +sublist => NULL() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif END PROCEDURE bnField_Initiate1 !---------------------------------------------------------------------------- @@ -136,115 +183,118 @@ MODULE PROCEDURE bnField_Initiate3 CHARACTER(*), PARAMETER :: myName = "bnField_Initiate3" CHARACTER(1), ALLOCATABLE :: physicalVarNames(:) -CHARACTER(:), ALLOCATABLE :: char_var -INTEGER(I4B) :: tVar, ii, ierror, storageFMT +TYPE(String) :: astr +INTEGER(I4B) :: tPhysicalVarNames, ii, ierr, storageFMT, tSize INTEGER(I4B), ALLOCATABLE :: timeCompo(:), spaceCompo(:), tNodes(:) +TYPE(ParameterList_), POINTER :: sublist + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'BlockNodeField_::obj is already initiated') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: BlockNodeField_::obj is already initiated.') + RETURN END IF -CALL obj%checkEssentialParam(param) +! main +sublist => NULL() -! engine -obj%engine = "NATIVE_SERIAL" - -! engine -ALLOCATE (CHARACTER( & - & param%DataSizeInBytes(key=myprefix//"/engine")) :: char_var) -ierror = param%get(key=myprefix//"/engine", VALUE=char_var) -obj%engine = char_var -DEALLOCATE (char_var) +ierr = param%GetSubList(key=myprefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + RETURN +END IF -! name -ALLOCATE (CHARACTER(param%DataSizeInBytes( & - & key=myprefix//"/name")) :: char_var) -ierror = param%get(key=myprefix//"/name", VALUE=char_var) -obj%name = char_var -DEALLOCATE (char_var) +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') + RETURN +END IF -! fieldType -ierror = param%get(key=myprefix//"/fieldType", & - & VALUE=obj%fieldType) +CALL obj%CheckEssentialParam(sublist) +CALL obj%DEALLOCATE() ! tPhysicalVarNames -ierror = param%get(key=myprefix//'/tPhysicalVarNames', VALUE=tVar) +CALL GetValue(obj=sublist, prefix=myprefix, key='tPhysicalVarNames', & + & VALUE=tPhysicalVarNames) -! check -IF (SIZE(dom) .NE. tVar) & - & CALL e%raiseError(modName//'::'//myName//" - "// & - & 'Size of dom not equal to the total number of physical variables') +! Check +ii = SIZE(dom) +IF (ii .NE. tPhysicalVarNames) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERRPR] :: Size of dom ('//tostring(ii)// & + & ') not equal to total number of physical variables ('// & + & tostring(tPhysicalVarNames)//')') + RETURN +END IF -! check -DO ii = 1, tVar +! Check +DO ii = 1, tPhysicalVarNames IF (.NOT. ASSOCIATED(dom(ii)%ptr)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'dom( '//TOSTRING(ii)//')%ptr is NOT ASSOCIATED!') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: dom( '//TOSTRING(ii)// & + & ')%ptr is NOT ASSOCIATED!') + RETURN END IF END DO ! allocate -CALL Reallocate(tNodes, tVar) -CALL Reallocate(timeCompo, tVar) -CALL Reallocate(spaceCompo, tVar) -ALLOCATE (physicalVarNames(tVar)) +CALL Reallocate(tNodes, tPhysicalVarNames) +CALL Reallocate(timeCompo, tPhysicalVarNames) +CALL Reallocate(spaceCompo, tPhysicalVarNames) +ALLOCATE (physicalVarNames(tPhysicalVarNames)) ! physicalVarName -DO ii = 1, tVar - ALLOCATE (CHARACTER(param%DataSizeInBytes( & - & key=myprefix//"/physicalVarName"//TOSTRING(ii))) :: char_var) - ierror = param%get(key=myprefix//"/physicalVarName" & - & //TOSTRING(ii), VALUE=char_var) - physicalVarNames(ii) (1:1) = char_var(1:1); DEALLOCATE (char_var) +DO ii = 1, tPhysicalVarNames + astr = "" + CALL GetValue(obj=sublist, prefix=myprefix, & + & key="physicalVarName"//tostring(ii), VALUE=astr) + physicalVarNames(ii) (1:1) = astr%slice(1, 1) END DO ! spaceCompo -IF (param%isPresent(key=myprefix//"/spaceCompo")) THEN - ierror = param%get(key=myprefix//"/spaceCompo", VALUE=spaceCompo) -END IF +CALL GetValue(obj=sublist, prefix=myprefix, key="spaceCompo", & + & VALUE=spaceCompo) ! timeCompo -IF (param%isPresent(key=myprefix//"/timeCompo")) THEN - ierror = param%get(key=myprefix//"/timeCompo", VALUE=timeCompo) -ELSE - timeCompo = 1 -END IF - -! storage format -storageFMT = FMT_DOF +timeCompo = 1_I4B +CALL GetValue(obj=sublist, prefix=myprefix, key="timeCompo", & + & VALUE=timeCompo) -! domains, tNodes -ALLOCATE (obj%domains(tvar)) -obj%tSize = 0 +storageFMT = DOF_FMT -DO ii = 1, tVar - obj%domains(ii)%ptr => dom(ii)%ptr - tNodes(ii) = obj%domains(ii)%ptr%getTotalNodes() - obj%tSize = obj%tSize + tNodes(ii) * timeCompo(ii) * spaceCompo(ii) +tSize = 0 +DO ii = 1, tPhysicalVarNames + tNodes(ii) = dom(ii)%ptr%GetTotalNodes() + tSize = tSize + tNodes(ii) * timeCompo(ii) * spaceCompo(ii) END DO -IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize -END IF -IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize -END IF - -! tNodes for constant field -IF (obj%fieldType .EQ. FIELD_TYPE_CONSTANT) THEN - tNodes(:) = 1 -END IF - -! DOF_ -CALL Initiate(obj=obj%dof, tNodes=tNodes, names=physicalVarNames, & - & spaceCompo=spaceCompo, timeCompo=timeCompo, storageFMT=storageFMT) - -! realVec -CALL Initiate(obj=obj%realVec, dofobj=obj%dof) - -obj%isInitiated = .TRUE. -DEALLOCATE (tNodes, spaceCompo, timeCompo, physicalVarNames) +CALL AbstractNodeFieldSetParam( & + & obj=obj, & + & dof_tPhysicalVars=tPhysicalVarNames, & + & dof_storageFMT=storageFMT, & + & dof_spaceCompo=spaceCompo, & + & dof_timeCompo=timeCompo, & + & dof_tNodes=tNodes, & + & dof_names_char=physicalVarNames, & + & tSize=tSize) + +CALL AbstractNodeFieldInitiate( & + & obj=obj, & + & param=param, & + & dom=dom, & + & prefix=myprefix) + +astr = "" +IF (ALLOCATED(physicalVarNames)) DEALLOCATE (physicalVarNames) +IF (ALLOCATED(timeCompo)) DEALLOCATE (timeCompo) +IF (ALLOCATED(spaceCompo)) DEALLOCATE (spaceCompo) +IF (ALLOCATED(tNodes)) DEALLOCATE (tNodes) +sublist => NULL() END PROCEDURE bnField_Initiate3 !---------------------------------------------------------------------------- diff --git a/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 b/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 index b15c784fe..104d5311e 100644 --- a/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 +++ b/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 @@ -24,37 +24,37 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get1 -CHARACTER(*), PARAMETER :: myName = "bnField_get1" +MODULE PROCEDURE bnField_Get1 +CHARACTER(*), PARAMETER :: myName = "bnField_Get1" IF (.NOT. obj%isInitiated) & & CALL e%raiseError(modName//'::'//myName//" - "// & & 'BlockNodeField_::obj is not initiated') VALUE = Get( & & obj=obj%realVec, & & dofobj=obj%dof, & - & nodenum=obj%domains(ivar)%ptr%getLocalNodeNumber(globalNode), & + & nodenum=obj%domains(ivar)%ptr%GetLocalNodeNumber(globalNode), & & ivar=ivar, & & idof=idof) -END PROCEDURE bnField_get1 +END PROCEDURE bnField_Get1 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get2 -CHARACTER(*), PARAMETER :: myName = "bnField_get2" +MODULE PROCEDURE bnField_Get2 +CHARACTER(*), PARAMETER :: myName = "bnField_Get2" IF (.NOT. obj%isInitiated) & & CALL e%raiseError(modName//'::'//myName//" - "// & & 'BlockNodeField_::obj is not initiated') VALUE = Get(obj=obj%realVec) -END PROCEDURE bnField_get2 +END PROCEDURE bnField_Get2 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get3 -CHARACTER(*), PARAMETER :: myName = "bnField_get3" +MODULE PROCEDURE bnField_Get3 +CHARACTER(*), PARAMETER :: myName = "bnField_Get3" IF (.NOT. obj%isInitiated) & & CALL e%raiseError(modName//'::'//myName//" - "// & & 'BlockNodeField_::obj is not initiated') @@ -62,49 +62,49 @@ VALUE = Get( & & obj=obj%realVec, & & dofobj=obj%dof, & - & nodenum=obj%domains(ivar)%ptr%getLocalNodeNumber(globalNode), & + & nodenum=obj%domains(ivar)%ptr%GetLocalNodeNumber(globalNode), & & ivar=ivar, & & idof=idof) -END PROCEDURE bnField_get3 +END PROCEDURE bnField_Get3 !---------------------------------------------------------------------------- -! get +! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get4 +MODULE PROCEDURE bnField_Get4 INTEGER(I4B) :: globalNode(INT(1 + (iend - istart) / stride)), ii, jj jj = 0 DO ii = istart, iend, stride jj = jj + 1 globalNode(jj) = ii END DO -CALL obj%get( & +CALL obj%Get( & & globalNode=globalNode, & & VALUE=VALUE, & & ivar=ivar, & & idof=idof) -END PROCEDURE bnField_get4 +END PROCEDURE bnField_Get4 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get5 +MODULE PROCEDURE bnField_Get5 REAL(DFP), ALLOCATABLE :: value0(:) -CALL obj%get(VALUE=value0, globalNode=globalNode, ivar=ivar, idof=idof) +CALL obj%Get(VALUE=value0, globalNode=globalNode, ivar=ivar, idof=idof) VALUE = NodalVariable( & & value0, & & TypeFEVariableScalar, & & TypeFEVariableSpace) DEALLOCATE (value0) -END PROCEDURE bnField_get5 +END PROCEDURE bnField_Get5 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get6 -CHARACTER(*), PARAMETER :: myName = "bnField_get6" +MODULE PROCEDURE bnField_Get6 +CHARACTER(*), PARAMETER :: myName = "bnField_Get6" INTEGER(I4B) :: timeCompo INTEGER(I4B) :: spaceCompo INTEGER(I4B) :: ierr @@ -120,7 +120,7 @@ CALL Reallocate(m3a, case_id, tdof, 1) DO ii = 1, tdof - CALL obj%get(VALUE=value0, globalNode=globalNode, & + CALL obj%Get(VALUE=value0, globalNode=globalNode, & & ivar=ivar, idof=ii) m3a(:, ii, 1) = value0 END DO @@ -175,19 +175,19 @@ IF (ALLOCATED(m3a)) DEALLOCATE (m3a) IF (ALLOCATED(m3b)) DEALLOCATE (m3b) -END PROCEDURE bnField_get6 +END PROCEDURE bnField_Get6 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get7 +MODULE PROCEDURE bnField_Get7 INTEGER(I4B) :: localNode(SIZE(globalNode)), idof -CHARACTER(*), PARAMETER :: myName = "bnField_get7" +CHARACTER(*), PARAMETER :: myName = "bnField_Get7" IF (.NOT. obj%isInitiated) & & CALL e%raiseError(modName//'::'//myName//" - "// & & 'BlockNodeField_::obj is not initiated') -localNode = obj%domains(ivar)%ptr%getLocalNodeNumber(globalNode) +localNode = obj%domains(ivar)%ptr%GetLocalNodeNumber(globalNode) IF (ANY(localNode .EQ. 0_I4B)) THEN CALL e%raiseError(modName//'::'//myName//' - '// & & 'Some of globalNodes are out of bound') @@ -196,29 +196,29 @@ & tSpaceCompo=obj%dof.SpaceComponents.ivar) VALUE = Get(obj=obj%realVec, dofobj=obj%dof, & & nodenum=localNode, ivar=ivar, idof=idof) -END PROCEDURE bnField_get7 +END PROCEDURE bnField_Get7 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get8 +MODULE PROCEDURE bnField_Get8 REAL(DFP), ALLOCATABLE :: value0(:) -CALL obj%get(VALUE=value0, globalNode=globalNode, ivar=ivar, & +CALL obj%Get(VALUE=value0, globalNode=globalNode, ivar=ivar, & & spaceCompo=spaceCompo, timeCompo=timeCompo) VALUE = NodalVariable( & & value0, & & TypeFEVariableScalar, & & TypeFEVariableSpace) DEALLOCATE (value0) -END PROCEDURE bnField_get8 +END PROCEDURE bnField_Get8 !---------------------------------------------------------------------------- ! Get !---------------------------------------------------------------------------- -MODULE PROCEDURE bnField_get9 -CHARACTER(*), PARAMETER :: myName = "bnField_get9" +MODULE PROCEDURE bnField_Get9 +CHARACTER(*), PARAMETER :: myName = "bnField_Get9" INTEGER(I4B) :: tsize INTEGER(I4B) :: tsize_value INTEGER(I4B) :: ii @@ -257,8 +257,17 @@ & idof=idof_value) CALL VALUE%SetSingle(VALUE=avar, indx=indx2) END DO +END PROCEDURE bnField_Get9 -END PROCEDURE bnField_get9 +!---------------------------------------------------------------------------- +! GetFEVariable +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bnField_GetFEVariable +INTEGER(I4B) :: ivar0 +ivar0 = input(option=ivar, default=1_I4B) +CALL obj%Get(globalNode=globalNode, VALUE=VALUE, ivar=ivar0) +END PROCEDURE bnField_GetFEVariable !---------------------------------------------------------------------------- ! From 19719ebca93689b6b9fb4ce8986e3fc4b7b9b3ab Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 18:31:56 +0900 Subject: [PATCH 049/117] Adding GetPrefix Method Fixing issue #202 Adding GetPrefix method for - ScalarField - STScalarField - VectorField - STVectorField - BlockNodeField --- .../AbstractField/src/AbstractField_Class.F90 | 16 ++++++++++++++++ .../src/BlockNodeField_Class.F90 | 16 ++++++++++++++++ .../STScalarField/src/STScalarField_Class.F90 | 16 ++++++++++++++++ .../STVectorField/src/STVectorField_Class.F90 | 18 ++++++++++++++++++ .../ScalarField/src/ScalarField_Class.F90 | 16 ++++++++++++++++ .../VectorField/src/VectorField_Class.F90 | 17 +++++++++++++++++ .../src/AbstractField_Class@GetMethods.F90 | 11 +++++++++++ .../src/BlockNodeField_Class@GetMethods.F90 | 8 ++++++++ .../src/STScalarField_Class@GetMethods.F90 | 8 ++++++++ .../src/STVectorField_Class@GetMethods.F90 | 10 +++++++++- .../src/ScalarField_Class@GetMethods.F90 | 8 ++++++++ .../src/VectorField_Class@GetMethods.F90 | 8 ++++++++ 12 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index bc621d26a..e18c9fde4 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -181,6 +181,7 @@ MODULE AbstractField_Class & => aField_isConstant !! It returns true if the field is constant field !! INFO: This routine should be implemented by child classes + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => aField_GetPrefix ! SET: ! @SetMethods @@ -708,4 +709,19 @@ MODULE FUNCTION aField_IsConstant(obj) RESULT(ans) END FUNCTION aField_IsConstant END INTERFACE +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION aField_GetPrefix(obj) RESULT(ans) + CLASS(AbstractField_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION aField_GetPrefix +END INTERFACE + END MODULE AbstractField_Class diff --git a/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 b/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 index 2d313db54..66833984d 100644 --- a/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 +++ b/src/modules/BlockNodeField/src/BlockNodeField_Class.F90 @@ -112,6 +112,7 @@ MODULE BlockNodeField_Class GENERIC, PUBLIC :: Get => Get1, Get2, Get3, Get4, & & Get5, Get6, Get7, Get8, Get9 PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => bnField_GetFEVariable + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bnField_GetPrefix ! SET: ! @DirichletBCMethods @@ -880,6 +881,21 @@ MODULE SUBROUTINE bnField_GetFeVariable(obj, globalNode, VALUE, ivar) END SUBROUTINE bnField_GetFeVariable END INTERFACE BlockFieldGetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION bnField_GetPrefix(obj) RESULT(ans) + CLASS(BlockNodeField_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION bnField_GetPrefix +END INTERFACE + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/modules/STScalarField/src/STScalarField_Class.F90 b/src/modules/STScalarField/src/STScalarField_Class.F90 index 1a4ead95e..7b41d2e01 100644 --- a/src/modules/STScalarField/src/STScalarField_Class.F90 +++ b/src/modules/STScalarField/src/STScalarField_Class.F90 @@ -131,6 +131,7 @@ MODULE STScalarField_Class & stsField_GetPointerOfComponent PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => stsField_GetFeVariable !! Get Finite Element variable + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => stsField_GetPrefix ! SET: ! @DirichletBCMethods @@ -1006,6 +1007,21 @@ MODULE SUBROUTINE stsField_GetFeVariable(obj, globalNode, VALUE, ivar) END SUBROUTINE stsField_GetFeVariable END INTERFACE STScalarFieldGetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION stsField_GetPrefix(obj) RESULT(ans) + CLASS(STScalarField_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION stsField_GetPrefix +END INTERFACE + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/modules/STVectorField/src/STVectorField_Class.F90 b/src/modules/STVectorField/src/STVectorField_Class.F90 index ba2858a6f..d4a3310b3 100644 --- a/src/modules/STVectorField/src/STVectorField_Class.F90 +++ b/src/modules/STVectorField/src/STVectorField_Class.F90 @@ -134,6 +134,9 @@ MODULE STVectorField_Class !! Get the entries of STVector field PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => & & stvField_GetFeVariable + !! Get multiple values in FEVariable + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => stvField_GetPrefix + !! Get prefix ! SET: ! @DirichletBCMethods @@ -980,6 +983,21 @@ MODULE SUBROUTINE stvField_GetFeVariable(obj, globalNode, VALUE, ivar) END SUBROUTINE stvField_GetFeVariable END INTERFACE STVectorFieldGetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION stvField_GetPrefix(obj) RESULT(ans) + CLASS(STVectorField_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION stvField_GetPrefix +END INTERFACE + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/modules/ScalarField/src/ScalarField_Class.F90 b/src/modules/ScalarField/src/ScalarField_Class.F90 index 944108f38..fa78526e7 100644 --- a/src/modules/ScalarField/src/ScalarField_Class.F90 +++ b/src/modules/ScalarField/src/ScalarField_Class.F90 @@ -113,6 +113,7 @@ MODULE ScalarField_Class !! Get the entries of scalar field PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => sField_GetFeVariable !! Get Finite Element variable + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => sField_GetPrefix ! SET: ! @DirichletBCMethods @@ -609,6 +610,21 @@ MODULE SUBROUTINE sField_GetFeVariable(obj, globalNode, VALUE, ivar) END SUBROUTINE sField_GetFeVariable END INTERFACE ScalarFieldGetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION sField_GetPrefix(obj) RESULT(ans) + CLASS(ScalarField_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION sField_GetPrefix +END INTERFACE + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/modules/VectorField/src/VectorField_Class.F90 b/src/modules/VectorField/src/VectorField_Class.F90 index 5674c634f..fb7d4f751 100644 --- a/src/modules/VectorField/src/VectorField_Class.F90 +++ b/src/modules/VectorField/src/VectorField_Class.F90 @@ -134,6 +134,8 @@ MODULE VectorField_Class & Get5, Get6, Get7, Get8, Get9, Get10, Get11 !! Get the entries of Vector field PROCEDURE, PUBLIC, PASS(obj) :: GetFEVariable => vField_GetFeVariable + !! Get multiple values in FEVariable + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => vField_GetPrefix ! SET: ! @DirichletBCMethods @@ -1008,6 +1010,21 @@ MODULE SUBROUTINE vField_GetFeVariable(obj, globalNode, VALUE, ivar) END SUBROUTINE vField_GetFeVariable END INTERFACE VectorFieldGetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION vField_GetPrefix(obj) RESULT(ans) + CLASS(VectorField_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION vField_GetPrefix +END INTERFACE + !---------------------------------------------------------------------------- ! ApplyDirichletBC@DBCMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 index ade189358..cc5fc8f53 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@GetMethods.F90 @@ -193,4 +193,15 @@ END IF END PROCEDURE aField_isConstant +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_GetPrefix +CHARACTER(*), PARAMETER :: myName = "aField_GetPrefix()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This method should be implemented by child class.') +ans = "" +END PROCEDURE aField_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 b/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 index 104d5311e..665410c52 100644 --- a/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 +++ b/src/submodules/BlockNodeField/src/BlockNodeField_Class@GetMethods.F90 @@ -269,6 +269,14 @@ CALL obj%Get(globalNode=globalNode, VALUE=VALUE, ivar=ivar0) END PROCEDURE bnField_GetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bnField_GetPrefix +ans = myprefix +END PROCEDURE bnField_GetPrefix + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 index b4ce5df99..b531c7693 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@GetMethods.F90 @@ -284,4 +284,12 @@ CALL obj%Get(globalNode=globalNode, VALUE=VALUE) END PROCEDURE stsField_GetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stsField_GetPrefix +ans = myprefix +END PROCEDURE stsField_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 b/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 index de41fb983..5f445dfc9 100644 --- a/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 +++ b/src/submodules/STVectorField/src/STVectorField_Class@GetMethods.F90 @@ -484,13 +484,21 @@ END PROCEDURE stvField_GetPointerOfComponent !---------------------------------------------------------------------------- -! GetFEVariable +! GetFEVariable !---------------------------------------------------------------------------- MODULE PROCEDURE stvField_GetFEVariable CALL obj%Get(VALUE=VALUE, globalNode=globalNode) END PROCEDURE stvField_GetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE stvField_GetPrefix +ans = myprefix +END PROCEDURE stvField_GetPrefix + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 index 1949716ad..6313d1a0e 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@GetMethods.F90 @@ -161,4 +161,12 @@ CALL obj%Get(VALUE=VALUE, globalNode=globalNode) END PROCEDURE sField_GetFEVariable +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE sField_GetPrefix +ans = myprefix +END PROCEDURE sField_GetPrefix + END SUBMODULE GetMethods diff --git a/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 b/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 index 0262042ca..4bfa7d948 100644 --- a/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 +++ b/src/submodules/VectorField/src/VectorField_Class@GetMethods.F90 @@ -288,4 +288,12 @@ & idof=spaceCompo) END PROCEDURE vField_GetPointerOfComponent +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE vField_GetPrefix +ans = myprefix +END PROCEDURE vField_GetPrefix + END SUBMODULE GetMethods From 2abf26be3147cf7baca16d90377cd9c8ba21fe17 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 18:44:01 +0900 Subject: [PATCH 050/117] Update AbstractField - Adding Initiate1 and Initiate3 methods to AbstractField_Class --- .../AbstractField/src/AbstractField_Class.F90 | 112 +++++++++--------- ...AbstractField_Class@ConstructorMethods.F90 | 109 +++++++++++++++++ 2 files changed, 164 insertions(+), 57 deletions(-) diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index e18c9fde4..6a6253477 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -112,14 +112,14 @@ MODULE AbstractField_Class ! CONSTRUCTOR: ! @ConstructorMethods - PROCEDURE(aField_checkEssentialParam), DEFERRED, PUBLIC, PASS(obj) :: & - & checkEssentialParam - !! check essential parameters - PROCEDURE(aField_Initiate1), DEFERRED, PUBLIC, PASS(obj) :: Initiate1 + PROCEDURE(aField_CheckEssentialParam), DEFERRED, PUBLIC, PASS(obj) :: & + & CheckEssentialParam + !! Check essential parameters + PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => aField_Initiate1 !! Initiate the field by reading param and given domain PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => aField_Initiate2 !! Initiate by copying other fields, and different options - PROCEDURE(aField_Initiate3), DEFERRED, PUBLIC, PASS(obj) :: Initiate3 + PROCEDURE, PUBLIC, PASS(obj) :: Initiate3 => aField_Initiate3 !! Initiate block fields (different physical variables) defined !! over different order of meshes. GENERIC, PUBLIC :: Initiate => Initiate1, Initiate2, Initiate3 @@ -195,7 +195,7 @@ MODULE AbstractField_Class !> authors: Vikas Sharma, Ph. D. ! date: 25 June 2021 -! summary: This routine check the essential parameters in param. +! summary: This routine Check the essential parameters in param. ABSTRACT INTERFACE SUBROUTINE aField_CheckEssentialParam(obj, param) @@ -205,35 +205,6 @@ SUBROUTINE aField_CheckEssentialParam(obj, param) END SUBROUTINE aField_CheckEssentialParam END INTERFACE -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 29 Sept 2021 -! summary: Initiate the field by reading param and given domain - -ABSTRACT INTERFACE - SUBROUTINE aField_Initiate1(obj, param, dom) - IMPORT :: AbstractField_, ParameterList_, Domain_ - CLASS(AbstractField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom - END SUBROUTINE aField_Initiate1 -END INTERFACE - -!---------------------------------------------------------------------------- -! CheckEssentialParam@ConstructorMethods -!---------------------------------------------------------------------------- - -INTERFACE - MODULE SUBROUTINE AbstractFieldCheckEssentialParam(obj, param, prefix) - CLASS(AbstractField_), INTENT(IN) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractFieldCheckEssentialParam -END INTERFACE - !---------------------------------------------------------------------------- ! SetAbstractFieldParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -267,38 +238,32 @@ END SUBROUTINE SetAbstractFieldParam END INTERFACE !---------------------------------------------------------------------------- -! Initiate@ConstructorMethods +! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- -!> authors: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Initiate the field by reading param and given domain - -INTERFACE AbstractFieldInitiate - MODULE SUBROUTINE AbstractFieldInitiate_1(obj, param, dom, prefix) - CLASS(AbstractField_), INTENT(INOUT) :: obj +INTERFACE + MODULE SUBROUTINE AbstractFieldCheckEssentialParam(obj, param, prefix) + CLASS(AbstractField_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractFieldInitiate_1 -END INTERFACE AbstractFieldInitiate + END SUBROUTINE AbstractFieldCheckEssentialParam +END INTERFACE !---------------------------------------------------------------------------- -! Initiate@ConstructorMethods +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. -! date: 2023-09-22 +! date: 29 Sept 2021 ! summary: Initiate the field by reading param and given domain -INTERFACE AbstractFieldInitiate - MODULE SUBROUTINE AbstractFieldInitiate_2(obj, param, dom, prefix) +INTERFACE + MODULE SUBROUTINE aField_Initiate1(obj, param, dom) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractFieldInitiate_2 -END INTERFACE AbstractFieldInitiate + TYPE(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE aField_Initiate1 +END INTERFACE !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods @@ -327,15 +292,48 @@ END SUBROUTINE aField_Initiate2 ! date: 29 Sept 2021 ! summary: Initiate by reading options from [[ParameterList_]] -ABSTRACT INTERFACE - SUBROUTINE aField_Initiate3(obj, param, dom) - IMPORT :: AbstractField_, ParameterList_, DomainPointer_ +INTERFACE + MODULE SUBROUTINE aField_Initiate3(obj, param, dom) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) END SUBROUTINE aField_Initiate3 END INTERFACE +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Initiate the field by reading param and given domain + +INTERFACE AbstractFieldInitiate + MODULE SUBROUTINE AbstractFieldInitiate_1(obj, param, dom, prefix) + CLASS(AbstractField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(Domain_), TARGET, INTENT(IN) :: dom + CHARACTER(*), INTENT(IN) :: prefix + END SUBROUTINE AbstractFieldInitiate_1 +END INTERFACE AbstractFieldInitiate + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2023-09-22 +! summary: Initiate the field by reading param and given domain + +INTERFACE AbstractFieldInitiate + MODULE SUBROUTINE AbstractFieldInitiate_2(obj, param, dom, prefix) + CLASS(AbstractField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) + CHARACTER(*), INTENT(IN) :: prefix + END SUBROUTINE AbstractFieldInitiate_2 +END INTERFACE AbstractFieldInitiate + !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 index e30f96c9e..01b78ac19 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 @@ -220,6 +220,53 @@ SUBROUTINE AbstractFieldInitiate_Help1(obj, param, prefix) CALL GetValue(obj=param, prefix=prefix, key="local_n", VALUE=obj%local_n) END SUBROUTINE AbstractFieldInitiate_Help1 +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Initiate1 +CHARACTER(*), PARAMETER :: myName = "aField_Initiate1()" +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr +CHARACTER(:), ALLOCATABLE :: prefix + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractFieldInitiate()') +#endif + +prefix = obj%GetPrefix() + +! main +sublist => NULL() +ierr = param%GetSubList(key=prefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') +END IF + +! NOTE: We should not call deallocate in abstract classes. +! This is because, in concrete classes we may set some +! parameters before calling this method. +! All those parameters will be gone if we call deallocate +! here. +! CALL obj%DEALLOCATE() + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') +END IF + +CALL AbstractFieldInitiate_Help1(obj, sublist, prefix) +obj%domain => dom +sublist => NULL() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractFieldInitiate()') +#endif +END PROCEDURE aField_Initiate1 + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- @@ -265,6 +312,68 @@ END SUBROUTINE AbstractFieldInitiate_Help1 #endif END PROCEDURE aField_Initiate2 +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE aField_Initiate3 +CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate_2()" +TYPE(ParameterList_), POINTER :: sublist +INTEGER(I4B) :: ierr, ii, tsize +LOGICAL(LGT) :: isOK +CHARACTER(:), ALLOCATABLE :: prefix + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractFieldInitiate()') +#endif + +prefix = obj%GetPrefix() + +! main +sublist => NULL() +ierr = param%GetSubList(key=prefix, sublist=sublist) +IF (ierr .NE. 0_I4B) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') + RETURN +END IF + +! NOTE: We should not call deallocate in abstract classes. +! This is because, in concrete classes we may set some +! parameters before calling this method. +! All those parameters will be gone if we call deallocate +! here. +! CALL obj%DEALLOCATE() + +IF (.NOT. ASSOCIATED(sublist)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') + RETURN +END IF + +CALL AbstractFieldInitiate_Help1(obj, sublist, prefix) + +tsize = SIZE(dom) +ALLOCATE (obj%domains(tsize)) +DO ii = 1, tsize + isOK = ASSOCIATED(dom(ii)%ptr) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: dom('//tostring(ii)//') is not ASSOCIATED.') + RETURN + END IF + obj%domains(ii)%ptr => dom(ii)%ptr +END DO + +sublist => NULL() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractFieldInitiate()') +#endif +END PROCEDURE aField_Initiate3 + !---------------------------------------------------------------------------- ! Deallocate !---------------------------------------------------------------------------- From 36ffaeaa8abeda1e976ac609e565ba888b3c6b81 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:01:53 +0900 Subject: [PATCH 051/117] Updates in AbstractField - Removing AbstractFieldInitiate method - Adding Initiate1 and Initiate 3 methods --- .../AbstractField/src/AbstractField_Class.F90 | 44 ++------ ...AbstractField_Class@ConstructorMethods.F90 | 103 ------------------ 2 files changed, 7 insertions(+), 140 deletions(-) diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90 b/src/modules/AbstractField/src/AbstractField_Class.F90 index 6a6253477..5c00ce83a 100644 --- a/src/modules/AbstractField/src/AbstractField_Class.F90 +++ b/src/modules/AbstractField/src/AbstractField_Class.F90 @@ -241,6 +241,10 @@ END SUBROUTINE SetAbstractFieldParam ! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Check essential param + INTERFACE MODULE SUBROUTINE AbstractFieldCheckEssentialParam(obj, param, prefix) CLASS(AbstractField_), INTENT(IN) :: obj @@ -257,13 +261,13 @@ END SUBROUTINE AbstractFieldCheckEssentialParam ! date: 29 Sept 2021 ! summary: Initiate the field by reading param and given domain -INTERFACE +INTERFACE AbstractFieldInitiate MODULE SUBROUTINE aField_Initiate1(obj, param, dom) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom END SUBROUTINE aField_Initiate1 -END INTERFACE +END INTERFACE AbstractFieldInitiate !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods @@ -292,46 +296,12 @@ END SUBROUTINE aField_Initiate2 ! date: 29 Sept 2021 ! summary: Initiate by reading options from [[ParameterList_]] -INTERFACE +INTERFACE AbstractFieldInitiate MODULE SUBROUTINE aField_Initiate3(obj, param, dom) CLASS(AbstractField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) END SUBROUTINE aField_Initiate3 -END INTERFACE - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Initiate the field by reading param and given domain - -INTERFACE AbstractFieldInitiate - MODULE SUBROUTINE AbstractFieldInitiate_1(obj, param, dom, prefix) - CLASS(AbstractField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractFieldInitiate_1 -END INTERFACE AbstractFieldInitiate - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Initiate the field by reading param and given domain - -INTERFACE AbstractFieldInitiate - MODULE SUBROUTINE AbstractFieldInitiate_2(obj, param, dom, prefix) - CLASS(AbstractField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractFieldInitiate_2 END INTERFACE AbstractFieldInitiate !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 index 01b78ac19..b2461f086 100644 --- a/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractField/src/AbstractField_Class@ConstructorMethods.F90 @@ -99,109 +99,6 @@ sublist => NULL() END PROCEDURE SetAbstractFieldParam -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE AbstractFieldInitiate_1 -CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate_1()" -TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] AbstractFieldInitiate()') -#endif - -! main -sublist => NULL() -ierr = param%GetSubList(key=prefix, sublist=sublist) -IF (ierr .NE. 0_I4B) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') -END IF - -! NOTE: We should not call deallocate in abstract classes. -! This is because, in concrete classes we may set some -! parameters before calling this method. -! All those parameters will be gone if we call deallocate -! here. -! CALL obj%DEALLOCATE() - -IF (.NOT. ASSOCIATED(sublist)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') -END IF - -CALL AbstractFieldInitiate_Help1(obj, sublist, prefix) -obj%domain => dom -sublist => NULL() - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] AbstractFieldInitiate()') -#endif -END PROCEDURE AbstractFieldInitiate_1 - -!---------------------------------------------------------------------------- -! Initiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE AbstractFieldInitiate_2 -CHARACTER(*), PARAMETER :: myName = "AbstractFieldInitiate_2()" -TYPE(ParameterList_), POINTER :: sublist -INTEGER(I4B) :: ierr, ii, tsize -LOGICAL(LGT) :: isOK - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] AbstractFieldInitiate()') -#endif - -! main -sublist => NULL() -ierr = param%GetSubList(key=prefix, sublist=sublist) -IF (ierr .NE. 0_I4B) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(1)') - RETURN -END IF - -! NOTE: We should not call deallocate in abstract classes. -! This is because, in concrete classes we may set some -! parameters before calling this method. -! All those parameters will be gone if we call deallocate -! here. -! CALL obj%DEALLOCATE() - -IF (.NOT. ASSOCIATED(sublist)) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: some error occured in getting sublist(2)') - RETURN -END IF - -CALL AbstractFieldInitiate_Help1(obj, sublist, prefix) - -tsize = SIZE(dom) -ALLOCATE (obj%domains(tsize)) -DO ii = 1, tsize - isOK = ASSOCIATED(dom(ii)%ptr) - IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: dom('//tostring(ii)//') is not ASSOCIATED.') - RETURN - END IF - obj%domains(ii)%ptr => dom(ii)%ptr -END DO - -sublist => NULL() - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] AbstractFieldInitiate()') -#endif -END PROCEDURE AbstractFieldInitiate_2 - !---------------------------------------------------------------------------- ! AbstractFieldInitiate_Help1 !---------------------------------------------------------------------------- From ca700c9ae4286b22d43e7317be91977904342761 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:04:59 +0900 Subject: [PATCH 052/117] Update in AbstractNodeField_ - Adding Initiate1 method - Adding Initiate2 method - Minor formatting --- .../src/AbstractNodeField_Class.F90 | 208 ++++++++++-------- ...ractNodeField_Class@ConstructorMethods.F90 | 109 ++++++++- 2 files changed, 216 insertions(+), 101 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index 0c7d58a65..b97f091b4 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -83,6 +83,8 @@ MODULE AbstractNodeField_Class ! CONSTRUCTOR: ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: Initiate1 => anf_Initiate1 + !! Initiate an instance of AbstrtactNodeField PROCEDURE, PUBLIC, PASS(obj) :: Initiate2 => anf_Initiate2 !! Initiate an instance of AbstrtactNodeField PROCEDURE, PUBLIC, PASS(obj) :: Initiate3 => anf_Initiate3 @@ -139,30 +141,7 @@ MODULE AbstractNodeField_Class END TYPE AbstractNodeFieldPointer_ !---------------------------------------------------------------------------- -! SetParam -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-10-25 -! summary: Set parameters of AbstractNodeField_ - -INTERFACE AbstractNodeFieldSetParam - MODULE SUBROUTINE anf_SetParam(obj, dof_tPhysicalVars, & - & dof_storageFMT, dof_spaceCompo, dof_timeCompo, & - & dof_tNodes, dof_names_char, tSize) - CLASS(AbstractNodeField_), INTENT(INOUT) :: obj - INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_tPhysicalVars - INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_storageFMT - INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_spaceCompo(:) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_timeCompo(:) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_tNodes(:) - CHARACTER(*), OPTIONAL, INTENT(IN) :: dof_names_char(:) - INTEGER(I4B), OPTIONAL, INTENT(IN) :: tSize - END SUBROUTINE anf_SetParam -END INTERFACE AbstractNodeFieldSetParam - -!---------------------------------------------------------------------------- -! Initiate +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -179,7 +158,7 @@ END SUBROUTINE AbstractNodeFieldInitiate1 END INTERFACE AbstractNodeFieldInitiate !---------------------------------------------------------------------------- -! Initiate +! Initiate@ConstructorMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -196,7 +175,7 @@ END SUBROUTINE AbstractNodeFieldInitiate2 END INTERFACE AbstractNodeFieldInitiate !---------------------------------------------------------------------------- -! CheckError +! CheckError@ConstructorMethods !---------------------------------------------------------------------------- INTERFACE @@ -206,9 +185,92 @@ END SUBROUTINE AbstractNodeFieldCheckError END INTERFACE !---------------------------------------------------------------------------- -! Display +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 29 Sept 2021 +! summary: Initiate the field by reading param and given domain + +INTERFACE + MODULE SUBROUTINE anf_Initiate1(obj, param, dom) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(Domain_), TARGET, INTENT(IN) :: dom + END SUBROUTINE anf_Initiate1 +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 25 Sept 2021 +! summary: Initiate AbstractNodeField_ from another instance +! +!# Introduction +! +! This method initiates an AbstractNodeField_ instance +! by copying all or some contents from another instance of AbstractNodeField_ +! +! If obj is not initiated then we copy everything +! For domain and domains we always use pointers +! +! If obj is initiated then we only copy the data stored in realvec +! +! +! Currently, copyStructure and usePointer is not used + +INTERFACE AbstractNodeFieldInitiate2 + MODULE SUBROUTINE anf_Initiate2(obj, obj2, copyFull, copyStructure, & + & usePointer) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + CLASS(AbstractField_), INTENT(INOUT) :: obj2 + !! It should be a child of AbstractNodeField_ + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyFull + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer + END SUBROUTINE anf_Initiate2 +END INTERFACE AbstractNodeFieldInitiate2 + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 25 Sept 2021 +! summary: Initiates AbstractNodeField_ from parameters and domain + +INTERFACE + MODULE SUBROUTINE anf_Initiate3(obj, param, dom) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) + END SUBROUTINE anf_Initiate3 +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 21 Oct 2021 +! summary: Deallocates data in [[AbstractNodeField_]] + +INTERFACE AbstractNodeFieldDeallocate + MODULE SUBROUTINE anf_Deallocate(obj) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + END SUBROUTINE anf_Deallocate +END INTERFACE AbstractNodeFieldDeallocate + +!---------------------------------------------------------------------------- +! Display@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Display the content of AbstractNodeField + INTERFACE AbstractNodeFieldDisplay MODULE SUBROUTINE anf_Display(obj, msg, unitNo) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj @@ -218,7 +280,7 @@ END SUBROUTINE anf_Display END INTERFACE AbstractNodeFieldDisplay !---------------------------------------------------------------------------- -! IMPORT +! IMPORT@IOMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -267,7 +329,7 @@ END SUBROUTINE anf_WriteData_vtk END INTERFACE AbstractNodeWriteData !---------------------------------------------------------------------------- -! GetPointer +! GetPointer@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. @@ -281,69 +343,6 @@ MODULE FUNCTION anf_GetPointer(obj) RESULT(ans) END FUNCTION anf_GetPointer END INTERFACE AbstractNodeFieldGetPointer -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 25 Sept 2021 -! summary: Initiate AbstractNodeField_ from another instance -! -!# Introduction -! -! This method initiates an AbstractNodeField_ instance -! by copying all or some contents from another instance of AbstractNodeField_ -! -! If obj is not initiated then we copy everything -! For domain and domains we always use pointers -! -! If obj is initiated then we only copy the data stored in realvec -! -! -! Currently, copyStructure and usePointer is not used - -INTERFACE AbstractNodeFieldInitiate2 - MODULE SUBROUTINE anf_Initiate2(obj, obj2, copyFull, copyStructure, & - & usePointer) - CLASS(AbstractNodeField_), INTENT(INOUT) :: obj - CLASS(AbstractField_), INTENT(INOUT) :: obj2 - !! It should be a child of AbstractNodeField_ - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyFull - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer - END SUBROUTINE anf_Initiate2 -END INTERFACE AbstractNodeFieldInitiate2 - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 25 Sept 2021 -! summary: Initiates AbstractNodeField_ from parameters and domain - -INTERFACE - MODULE SUBROUTINE anf_Initiate3(obj, param, dom) - CLASS(AbstractNodeField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) - END SUBROUTINE anf_Initiate3 -END INTERFACE - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 21 Oct 2021 -! summary: Deallocates data in [[AbstractNodeField_]] - -INTERFACE AbstractNodeFieldDeallocate - MODULE SUBROUTINE anf_Deallocate(obj) - CLASS(AbstractNodeField_), INTENT(INOUT) :: obj - END SUBROUTINE anf_Deallocate -END INTERFACE AbstractNodeFieldDeallocate - !---------------------------------------------------------------------------- ! Norm2@GetMethods !---------------------------------------------------------------------------- @@ -359,6 +358,29 @@ MODULE FUNCTION anf_Norm2(obj) RESULT(ans) END FUNCTION anf_Norm2 END INTERFACE +!---------------------------------------------------------------------------- +! SetParam@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-10-25 +! summary: Set parameters of AbstractNodeField_ + +INTERFACE AbstractNodeFieldSetParam + MODULE SUBROUTINE anf_SetParam(obj, dof_tPhysicalVars, & + & dof_storageFMT, dof_spaceCompo, dof_timeCompo, & + & dof_tNodes, dof_names_char, tSize) + CLASS(AbstractNodeField_), INTENT(INOUT) :: obj + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_tPhysicalVars + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_storageFMT + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_spaceCompo(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_timeCompo(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dof_tNodes(:) + CHARACTER(*), OPTIONAL, INTENT(IN) :: dof_names_char(:) + INTEGER(I4B), OPTIONAL, INTENT(IN) :: tSize + END SUBROUTINE anf_SetParam +END INTERFACE AbstractNodeFieldSetParam + !---------------------------------------------------------------------------- ! SetSingle@SetMethods !---------------------------------------------------------------------------- @@ -476,7 +498,7 @@ END FUNCTION anf_GetTimeCompo END INTERFACE !---------------------------------------------------------------------------- -! Size +! Size@GetMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 index 1ecf39bc3..b49bad62f 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 @@ -32,7 +32,7 @@ & '[START] AbstractNodeFieldInitiate()') #endif -CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) +CALL AbstractFieldInitiate(obj=obj, param=param, dom=dom) #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & @@ -81,7 +81,7 @@ & '[START] AbstractNodeFieldInitiate()') #endif -CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) +CALL AbstractFieldInitiate(obj=obj, param=param, dom=dom) #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & @@ -125,8 +125,6 @@ INTEGER(I4B) :: ivar, tvar LOGICAL(LGT) :: isNOTOK -! CALL AbstractFieldInitiate(obj=obj, param=param, prefix=prefix, dom=dom) - isNOTOK = obj%dof_tPhysicalVars .EQ. 0_I4B IF (isNOTOK) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & @@ -205,6 +203,58 @@ END IF END PROCEDURE AbstractNodeFieldCheckError +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_Initiate1 +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate1()" +CHARACTER(:), ALLOCATABLE :: prefix + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractNodeFieldInitiate()') +#endif + +prefix = obj%GetPrefix() + +CALL AbstractFieldInitiate(obj=obj, param=param, dom=dom) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'Calling AbstractNodeFieldCheckError()') +#endif + +CALL AbstractNodeFieldCheckError(obj) + +CALL Initiate( & + & obj=obj%dof, & + & tNodes=obj%dof_tNodes, & + & names=obj%dof_names_char, & + & spaceCompo=obj%dof_spaceCompo, & + & timeCompo=obj%dof_timeCompo, & + & storageFMT=obj%dof_storageFMT) + +CALL Initiate(obj=obj%realVec, dofobj=obj%dof) + +obj%tSize = SIZE(obj%realVec) + +IF (obj%local_n .EQ. 0) THEN + obj%local_n = obj%tSize +END IF + +IF (obj%global_n .EQ. 0) THEN + obj%global_n = obj%tSize +END IF + +prefix = "" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractNodeFieldInitiate()') +#endif +END PROCEDURE anf_Initiate1 + !---------------------------------------------------------------------------- ! Initiate2 !---------------------------------------------------------------------------- @@ -234,10 +284,53 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE anf_Initiate3 -CHARACTER(*), PARAMETER :: myName = "anf_Initiate3" -CALL e%raiseError(modName//'::'//myName//" - "// & - & '[IMPLEMENTATION ERROR] :: Initiate3 should be implemented by the'// & - & ' child of AbstractNodeField_') +CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate2()" +INTEGER(I4B) :: ivar, tvar +LOGICAL(LGT) :: isNOTOK +CHARACTER(:), ALLOCATABLE :: prefix + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] AbstractNodeFieldInitiate()') +#endif + +prefix = obj%GetPrefix() + +CALL AbstractFieldInitiate(obj=obj, param=param, dom=dom) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'Calling AbstractNodeFieldCheckError()') +#endif + +CALL AbstractNodeFieldCheckError(obj) + +CALL Initiate( & + & obj=obj%dof, & + & tNodes=obj%dof_tNodes, & + & names=obj%dof_names_char, & + & spaceCompo=obj%dof_spaceCompo, & + & timeCompo=obj%dof_timeCompo, & + & storageFMT=obj%dof_storageFMT) + +CALL Initiate(obj=obj%realVec, dofobj=obj%dof) + +obj%tSize = SIZE(obj%realVec) + +IF (obj%local_n .EQ. 0) THEN + obj%local_n = obj%tSize +END IF + +IF (obj%global_n .EQ. 0) THEN + obj%global_n = obj%tSize +END IF + +prefix = "" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] AbstractNodeFieldInitiate()') +#endif END PROCEDURE anf_Initiate3 !---------------------------------------------------------------------------- From 4153f3b46bce52fc5626b096dbb5a2f8485ff496 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:16:51 +0900 Subject: [PATCH 053/117] Updates in AbstractNodeField - Removing AbstractNodeFieldInitiate1 - removing AbstractNodeFieldInitiate2 - adding initiate1 - adding initiate2 --- .../src/AbstractNodeField_Class.F90 | 42 +------- ...ractNodeField_Class@ConstructorMethods.F90 | 97 ------------------- 2 files changed, 4 insertions(+), 135 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index b97f091b4..ec419563f 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -140,40 +140,6 @@ MODULE AbstractNodeField_Class CLASS(AbstractNodeField_), POINTER :: ptr => NULL() END TYPE AbstractNodeFieldPointer_ -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Initiate an instance of AbstractNodeField - -INTERFACE AbstractNodeFieldInitiate - MODULE SUBROUTINE AbstractNodeFieldInitiate1(obj, param, dom, prefix) - CLASS(AbstractNodeField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(Domain_), TARGET, INTENT(IN) :: dom - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractNodeFieldInitiate1 -END INTERFACE AbstractNodeFieldInitiate - -!---------------------------------------------------------------------------- -! Initiate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-22 -! summary: Initiate an instance of AbstractNodeField - -INTERFACE AbstractNodeFieldInitiate - MODULE SUBROUTINE AbstractNodeFieldInitiate2(obj, param, dom, prefix) - CLASS(AbstractNodeField_), INTENT(INOUT) :: obj - TYPE(ParameterList_), INTENT(IN) :: param - TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) - CHARACTER(*), INTENT(IN) :: prefix - END SUBROUTINE AbstractNodeFieldInitiate2 -END INTERFACE AbstractNodeFieldInitiate - !---------------------------------------------------------------------------- ! CheckError@ConstructorMethods !---------------------------------------------------------------------------- @@ -192,13 +158,13 @@ END SUBROUTINE AbstractNodeFieldCheckError ! date: 29 Sept 2021 ! summary: Initiate the field by reading param and given domain -INTERFACE +INTERFACE AbstractNodeFieldInitiate MODULE SUBROUTINE anf_Initiate1(obj, param, dom) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom END SUBROUTINE anf_Initiate1 -END INTERFACE +END INTERFACE AbstractNodeFieldInitiate !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods @@ -241,13 +207,13 @@ END SUBROUTINE anf_Initiate2 ! date: 25 Sept 2021 ! summary: Initiates AbstractNodeField_ from parameters and domain -INTERFACE +INTERFACE AbstractNodeFieldInitiate MODULE SUBROUTINE anf_Initiate3(obj, param, dom) CLASS(AbstractNodeField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) END SUBROUTINE anf_Initiate3 -END INTERFACE +END INTERFACE AbstractNodeFieldInitiate !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 index b49bad62f..1454bfa34 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@ConstructorMethods.F90 @@ -20,102 +20,6 @@ IMPLICIT NONE CONTAINS -!---------------------------------------------------------------------------- -! AbstractNodeFieldInitiate -!---------------------------------------------------------------------------- - -MODULE PROCEDURE AbstractNodeFieldInitiate1 -CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate1()" - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] AbstractNodeFieldInitiate()') -#endif - -CALL AbstractFieldInitiate(obj=obj, param=param, dom=dom) - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & 'Calling AbstractNodeFieldCheckError()') -#endif - -CALL AbstractNodeFieldCheckError(obj) - -CALL Initiate( & - & obj=obj%dof, & - & tNodes=obj%dof_tNodes, & - & names=obj%dof_names_char, & - & spaceCompo=obj%dof_spaceCompo, & - & timeCompo=obj%dof_timeCompo, & - & storageFMT=obj%dof_storageFMT) - -CALL Initiate(obj=obj%realVec, dofobj=obj%dof) - -obj%tSize = SIZE(obj%realVec) - -IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize -END IF - -IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize -END IF - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] AbstractNodeFieldInitiate()') -#endif -END PROCEDURE AbstractNodeFieldInitiate1 - -!---------------------------------------------------------------------------- -! AbstractNodeFieldInitiate2 -!---------------------------------------------------------------------------- - -MODULE PROCEDURE AbstractNodeFieldInitiate2 -CHARACTER(*), PARAMETER :: myName = "AbstractNodeFieldInitiate2()" -INTEGER(I4B) :: ivar, tvar -LOGICAL(LGT) :: isNOTOK - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] AbstractNodeFieldInitiate()') -#endif - -CALL AbstractFieldInitiate(obj=obj, param=param, dom=dom) - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & 'Calling AbstractNodeFieldCheckError()') -#endif - -CALL AbstractNodeFieldCheckError(obj) - -CALL Initiate( & - & obj=obj%dof, & - & tNodes=obj%dof_tNodes, & - & names=obj%dof_names_char, & - & spaceCompo=obj%dof_spaceCompo, & - & timeCompo=obj%dof_timeCompo, & - & storageFMT=obj%dof_storageFMT) - -CALL Initiate(obj=obj%realVec, dofobj=obj%dof) - -obj%tSize = SIZE(obj%realVec) - -IF (obj%local_n .EQ. 0) THEN - obj%local_n = obj%tSize -END IF - -IF (obj%global_n .EQ. 0) THEN - obj%global_n = obj%tSize -END IF - -#ifdef DEBUG_VER -CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] AbstractNodeFieldInitiate()') -#endif -END PROCEDURE AbstractNodeFieldInitiate2 - !---------------------------------------------------------------------------- ! AbstractNodeFieldCheckError !---------------------------------------------------------------------------- @@ -276,7 +180,6 @@ obj%realVec = obj2%realVec obj%dof = obj2%dof END SELECT - END PROCEDURE anf_Initiate2 !---------------------------------------------------------------------------- From 554c12daaae72ec211140b8d30f3c9962e653ad4 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:17:03 +0900 Subject: [PATCH 054/117] Update BlockNodeField_Class@ConstructorMethods.F90 - Updates in Initiate method --- .../src/BlockNodeField_Class@ConstructorMethods.F90 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 b/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 index 0b2b92eca..c209483d2 100644 --- a/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 +++ b/src/submodules/BlockNodeField/src/BlockNodeField_Class@ConstructorMethods.F90 @@ -283,11 +283,7 @@ & dof_names_char=physicalVarNames, & & tSize=tSize) -CALL AbstractNodeFieldInitiate( & - & obj=obj, & - & param=param, & - & dom=dom, & - & prefix=myprefix) +CALL AbstractNodeFieldInitiate(obj=obj, param=param, dom=dom) astr = "" IF (ALLOCATED(physicalVarNames)) DEALLOCATE (physicalVarNames) From 65815359de9fbaed928b6d877ebc5431d7503a7e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:17:06 +0900 Subject: [PATCH 055/117] Update ScalarField_Class@ConstructorMethods.F90 - Updates in Initiate method --- .../ScalarField/src/ScalarField_Class@ConstructorMethods.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 index 31ab4ef00..391298232 100644 --- a/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/ScalarField/src/ScalarField_Class@ConstructorMethods.F90 @@ -92,8 +92,7 @@ CALL AbstractNodeFieldInitiate( & & obj=obj, & & param=param, & - & dom=dom, & - & prefix=myprefix) + & dom=dom) astr = "" sublist => NULL() From 7faf27a15734d50faf961bec89ecae078bd0950e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:17:08 +0900 Subject: [PATCH 056/117] Update STScalarField_Class@ConstructorMethods.F90 - Updates in Initiate method --- .../src/STScalarField_Class@ConstructorMethods.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 index 115c4bead..85a240115 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@ConstructorMethods.F90 @@ -127,8 +127,7 @@ CALL AbstractNodeFieldInitiate( & & obj=obj, & & param=param, & - & dom=dom, & - & prefix=myprefix) + & dom=dom) astr = "" sublist => NULL() From d94892ccff76eb2fdd45f034b48bfa7164b9b7ea Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:17:11 +0900 Subject: [PATCH 057/117] Update STVectorField_Class@ConstructorMethods.F90 - Updates in Initiate method --- .../src/STVectorField_Class@ConstructorMethods.F90 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 index 6dc555141..94a1a8eff 100644 --- a/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/STVectorField/src/STVectorField_Class@ConstructorMethods.F90 @@ -135,11 +135,7 @@ nsd = dom%GetNSD() -CALL AbstractNodeFieldInitiate( & - & obj=obj, & - & param=param, & - & dom=dom, & - & prefix=myprefix) +CALL AbstractNodeFieldInitiate(obj=obj, param=param, dom=dom) astr = "" sublist => NULL() From 5a44cdf9db0532ff25c048180f6de4b5374121ce Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Sun, 26 Nov 2023 19:17:14 +0900 Subject: [PATCH 058/117] Update VectorField_Class@ConstructorMethods.F90 - Updates in Initiate method --- .../src/VectorField_Class@ConstructorMethods.F90 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 b/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 index 1e0d4d1af..889674ebd 100644 --- a/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 +++ b/src/submodules/VectorField/src/VectorField_Class@ConstructorMethods.F90 @@ -123,11 +123,7 @@ nsd = dom%GetNSD() -CALL AbstractNodeFieldInitiate( & - & obj=obj, & - & param=param, & - & dom=dom, & - & prefix=myprefix) +CALL AbstractNodeFieldInitiate(obj=obj, param=param, dom=dom) astr = "" sublist => NULL() From 13c33678a89cdd37b6bda2d8703fcda317940cf5 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Mon, 27 Nov 2023 17:22:35 +0900 Subject: [PATCH 059/117] Update MeshSelection_Class@GetNodeNumMethods.F90 Fixing a bug in GetNodeNum routine. Now, instead of unallocated vector we return vector of zero size. --- .../MeshSelection_Class@GetNodeNumMethods.F90 | 63 ++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 b/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 index db7250a0a..78608d2b1 100644 --- a/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 +++ b/src/submodules/MeshSelection/src/MeshSelection_Class@GetNodeNumMethods.F90 @@ -18,32 +18,43 @@ ! date: 28 Aug 2021 ! summary: This module defines a data type for mesh selection -SUBMODULE(MeshSelection_Class) GetNodeNumMethods +SUBMODULE(MeshSelection_Class) GetnodeNumMethods USE BaseMethod USE Mesh_Class, ONLY: Mesh_ IMPLICIT NONE CONTAINS !---------------------------------------------------------------------------- -! GetNodeNum +! GetnodeNum !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_GetNodeNum1 -IF (isAllocated(obj%NodeNum)) ans = obj%NodeNum -END PROCEDURE meshSelect_GetNodeNum1 +MODULE PROCEDURE meshSelect_GetnodeNum1 +IF (isAllocated(obj%nodeNum)) THEN + CALL Reallocate(ans, SIZE(obj%nodeNum)) + ans = obj%nodeNum +ELSE + CALL reallocate(ans, 0_I4B) +END IF +END PROCEDURE meshSelect_GetnodeNum1 !---------------------------------------------------------------------------- -! GetNodeNum +! GetnodeNum !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_GetNodeNum2 +MODULE PROCEDURE meshSelect_GetnodeNum2 +CHARACTER(*), PARAMETER :: myName = "meshSelect_GetnodeNum2()" TYPE(IntVector_) :: aintvec INTEGER(I4B), ALLOCATABLE :: indx(:) INTEGER(I4B) :: ii -! isSelectionByNodeNum -IF (obj%isSelectionByNodeNum) THEN - CALL APPEND(aintvec, obj%GetNodeNum()) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GetnodeNum()') +#endif + +! isSelectionBynodeNum +IF (obj%isSelectionBynodeNum) THEN + CALL APPEND(aintvec, obj%GetnodeNum()) END IF ! isSelectionByMeshID @@ -70,30 +81,37 @@ IF (isAllocated(aIntVec)) THEN CALL RemoveDuplicates(aIntVec) + CALL Reallocate(ans, SIZE(aintvec)) ans = aIntVec CALL DEALLOCATE (aIntVec) +ELSE + CALL Reallocate(ans, 0_I4B) END IF -END PROCEDURE meshSelect_GetNodeNum2 +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GetnodeNum()') +#endif +END PROCEDURE meshSelect_GetnodeNum2 !---------------------------------------------------------------------------- -! GetNodeNum +! GetnodeNum !---------------------------------------------------------------------------- -MODULE PROCEDURE meshSelect_GetNodeNum3 -CHARACTER(*), PARAMETER :: myName = "meshSelect_GetNodeNum3" +MODULE PROCEDURE meshSelect_GetnodeNum3 +CHARACTER(*), PARAMETER :: myName = "meshSelect_GetnodeNum3" TYPE(IntVector_) :: aintvec INTEGER(I4B), ALLOCATABLE :: indx(:), nptrs(:) INTEGER(I4B) :: ii, dim, nsd #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[START] GetNodeNum()') + & '[START] GetnodeNum()') #endif -! isSelectionByNodeNum -IF (obj%isSelectionByNodeNum) THEN - nptrs = obj%GetNodeNum() +! isSelectionBynodeNum +IF (obj%isSelectionBynodeNum) THEN + nptrs = obj%GetnodeNum() IF (ALLOCATED(nptrs)) THEN CALL APPEND(aintvec, nptrs) DEALLOCATE (nptrs) @@ -129,14 +147,17 @@ IF (isAllocated(aIntVec)) THEN CALL RemoveDuplicates(aIntVec) + CALL Reallocate(ans, SIZE(aIntVec)) ans = aIntVec CALL DEALLOCATE (aIntVec) +ELSE + CALL Reallocate(ans, 0_I4B) END IF #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] GetNodeNum()') + & '[END] GetnodeNum()') #endif -END PROCEDURE meshSelect_GetNodeNum3 +END PROCEDURE meshSelect_GetnodeNum3 -END SUBMODULE GetNodeNumMethods +END SUBMODULE GetnodeNumMethods From ee7361521bf21c411c43001ba26e73dd1fd25570 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Mon, 27 Nov 2023 17:53:53 +0900 Subject: [PATCH 060/117] Update UserFunction_Class@ConstructorMethods.F90 Fixing a bug in SetUserFunctionParam method. --- .../src/UserFunction_Class@ConstructorMethods.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 index ad66c0fa8..dfc33902e 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@ConstructorMethods.F90 @@ -139,7 +139,7 @@ END IF IF (argType .EQ. Constant) THEN - IF (numArgs .NE. 0) THEN + IF (numArgs0 .NE. 0) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: When argType is Constant, then '// & & 'numArgs should be 0.') @@ -148,7 +148,7 @@ END IF IF (argType .EQ. Time) THEN - IF (numArgs .NE. 1) THEN + IF (numArgs0 .NE. 1) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: When argType is Time, then '// & & 'numArgs should be 1.') @@ -157,7 +157,7 @@ END IF IF (argType .EQ. Space) THEN - IF (numArgs .NE. 3) THEN + IF (numArgs0 .NE. 3) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: When argType is Space, then '// & & 'numArgs should be 3.') @@ -166,7 +166,7 @@ END IF IF (argType .EQ. SpaceTime) THEN - IF (numArgs .NE. SpaceTime) THEN + IF (numArgs0 .NE. 4) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: When argType is SpaceTime, then '// & & 'numArgs should be 4.') From b8259371cd68548d0fde01610294ee3b8e0ea0da Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Mon, 27 Nov 2023 18:03:37 +0900 Subject: [PATCH 061/117] Update Domain_Class@GetMethods.F90 Fixing a bug in Domain_GetNodeCoord2 --- src/submodules/Domain/src/Domain_Class@GetMethods.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/submodules/Domain/src/Domain_Class@GetMethods.F90 b/src/submodules/Domain/src/Domain_Class@GetMethods.F90 index 964395e66..819a5444b 100644 --- a/src/submodules/Domain/src/Domain_Class@GetMethods.F90 +++ b/src/submodules/Domain/src/Domain_Class@GetMethods.F90 @@ -396,7 +396,7 @@ INTEGER(I4B) :: nsd localNode = obj%GetLocalNodeNumber(globalNode=globalNode) nsd = SIZE(nodeCoord, 1) -nodeCoord = nodeCoord(1:nsd, localNode) +nodeCoord = obj%nodeCoord(1:nsd, localNode) END PROCEDURE Domain_GetNodeCoord2 !---------------------------------------------------------------------------- From db05880629cfecfe101dbdd42c2f3950e94a88ca Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 00:44:21 +0900 Subject: [PATCH 062/117] Update UserFunction_Class.F90 Fixing a bug in `auf_Set1` method. --- src/modules/UserFunction/src/UserFunction_Class.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/UserFunction/src/UserFunction_Class.F90 b/src/modules/UserFunction/src/UserFunction_Class.F90 index 4342fef4d..6c3465b1f 100644 --- a/src/modules/UserFunction/src/UserFunction_Class.F90 +++ b/src/modules/UserFunction/src/UserFunction_Class.F90 @@ -103,7 +103,7 @@ MODULE UserFunction_Class CONTAINS PRIVATE - + ! CONSTRUCTOR: ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & @@ -516,10 +516,10 @@ SUBROUTINE auf_Set1(obj, scalarValue, vectorValue, matrixValue, & END IF IF (PRESENT(scalarValue)) THEN - isNotOK = (obj%argType .NE. Constant) .OR. (obj%returnType .NE. Scalar) + isNotOK = obj%returnType .NE. Scalar IF (isNotOK) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: UserFunction_::obj%argType is NOT Constant '// & + & '[INTERNAL ERROR] :: UserFunction_::obj%argType is NOT Constant '// & & ' or UserFunction_::obj%returnType is not Scalar') RETURN END IF @@ -527,7 +527,7 @@ SUBROUTINE auf_Set1(obj, scalarValue, vectorValue, matrixValue, & END IF IF (PRESENT(vectorValue)) THEN - isNotOK = (obj%argType .NE. Constant) .OR. (obj%returnType .NE. Vector) + isNotOK = obj%returnType .NE. Vector IF (isNotOK) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: UserFunction_::obj%argType '// & @@ -549,7 +549,7 @@ SUBROUTINE auf_Set1(obj, scalarValue, vectorValue, matrixValue, & END IF IF (PRESENT(matrixValue)) THEN - isNotOK = (obj%argType .NE. Constant) .OR. (obj%returnType .NE. Matrix) + isNotOK = obj%returnType .NE. Matrix IF (isNotOK) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[INTERNAL ERROR] :: UserFunction_::obj%argType '// & From db1407f71c0bc70496477750351b8f1cb2cfcbe0 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 00:44:57 +0900 Subject: [PATCH 063/117] Updates in AbstractBC Fixes issue #205 --- .../AbstractBC/src/AbstractBC_Class.F90 | 146 ++++++--- .../AbstractBC_Class@ConstructorMethods.F90 | 25 +- .../src/AbstractBC_Class@GetMethods.F90 | 289 +++++++++++++----- .../src/AbstractBC_Class@IOMethods.F90 | 210 ++++++++----- .../src/AbstractBC_Class@SetMethods.F90 | 36 ++- 5 files changed, 485 insertions(+), 221 deletions(-) diff --git a/src/modules/AbstractBC/src/AbstractBC_Class.F90 b/src/modules/AbstractBC/src/AbstractBC_Class.F90 index ca1e9526f..dd7b14511 100644 --- a/src/modules/AbstractBC/src/AbstractBC_Class.F90 +++ b/src/modules/AbstractBC/src/AbstractBC_Class.F90 @@ -22,6 +22,7 @@ MODULE AbstractBC_Class USE MeshSelection_Class USE Domain_Class USE HDF5File_Class +USE UserFunction_Class USE FPL, ONLY: ParameterList_ USE tomlf, ONLY: toml_table USE TxtFile_Class @@ -31,8 +32,9 @@ MODULE AbstractBC_Class CHARACTER(*), PARAMETER :: default_name = "AbstractBC" INTEGER(I4B), PARAMETER :: default_idof = 0_I4B INTEGER(I4B), PARAMETER :: default_nodalValueType = -1_I4B -CHARACTER(*) , PARAMETER :: default_nodalValueType_char = "NONE" +CHARACTER(*), PARAMETER :: default_nodalValueType_char = "NONE" LOGICAL(LGT), PARAMETER :: default_useFunction = .FALSE. +LOGICAL(LGT), PARAMETER :: default_isUserFunction = .FALSE. LOGICAL(LGT), PARAMETER :: default_isNormal = .FALSE. LOGICAL(LGT), PARAMETER :: default_isTangent = .FALSE. LOGICAL(LGT), PARAMETER :: default_useExternal = .FALSE. @@ -62,10 +64,7 @@ MODULE AbstractBC_Class INTEGER(I4B) :: idof = default_idof !! degree of freedom number INTEGER(I4B) :: nodalValueType = default_nodalValueType - !! Constant - !! Space - !! Time - !! SpaceTime + !! Constant, Space, SpaceTime, Time LOGICAL(LGT) :: useFunction = default_useFunction !! True if the boundary condition is analytical LOGICAL(LGT) :: isNormal = default_isNormal @@ -77,6 +76,8 @@ MODULE AbstractBC_Class !! depending upon the context. !! Basically we do not use the nodal value stored in the !! instance of AbstractBC_ + LOGICAL(LGT) :: isUserFunction = default_isUserFunction + !! True if userFunction is set REAL(DFP), ALLOCATABLE :: nodalValue(:, :) !! nodal values are kept here, !! nodalValues( :, its ) denotes nodal values at time step its @@ -88,7 +89,9 @@ MODULE AbstractBC_Class !! Space Function PROCEDURE(iface_TimeFunction), POINTER, NOPASS :: & & timeFunction => NULL() - !! Time Function + !! Time function + CLASS(UserFunction_), POINTER :: func => NULL() + !! User function TYPE(MeshSelection_) :: boundary !! Boundary CLASS(Domain_), POINTER :: dom => NULL() @@ -99,17 +102,25 @@ MODULE AbstractBC_Class ! CONSTRUCTOR: ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => bc_Deallocate + !! Deallocate memory occupied by AbstractBC PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & bc_CheckEssentialParam + !! Check essential parameter PROCEDURE, PUBLIC, PASS(obj) :: Initiate => bc_Initiate + !! Initiate an instance of AbstractBC ! IO: ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => bc_Import + !! Import data from HDF5File PROCEDURE, PUBLIC, PASS(obj) :: Export => bc_Export + !! Export data to HDF5File PROCEDURE, PUBLIC, PASS(obj) :: Display => bc_Display + !! Display content of AbstractBC PROCEDURE, PASS(obj) :: ImportFromToml1 => bc_ImportFromToml1 + !! Initiate from toml PROCEDURE, PASS(obj) :: ImportFromToml2 => bc_ImportFromToml2 + !! Initiate from toml GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, & & ImportFromToml2 !! Import abstract kernel from toml @@ -123,15 +134,24 @@ MODULE AbstractBC_Class ! GET: ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetMeshID => bc_GetMeshID + !! Get MeshID PROCEDURE, PUBLIC, PASS(obj) :: Get1 => bc_Get + !! Get value of boundary condition PROCEDURE, PUBLIC, PASS(obj) :: Get2 => bc_GetFEVar + !! Get value of boundary condition in FEVariable_ GENERIC, PUBLIC :: Get => Get1, Get2 + !! Generic method to get the boundary condition PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction + !! Get value from function + PROCEDURE, PUBLIC, PASS(obj) :: GetFromUserFunction => & + & bc_GetFromUserFunction + !! Get value from userfunction PROCEDURE, PUBLIC, PASS(obj) :: GetDOFNo => bc_GetDOFNo + !! Get degree of freedom number PROCEDURE, PUBLIC, PASS(obj) :: GetQuery => bc_GetQuery PROCEDURE, PUBLIC, PASS(obj) :: GetParam => bc_GetQuery PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => bc_GetPrefix - PROCEDURE, PUBLIC, PASS(obj) :: isUseFunction => bc_isUseFunction + PROCEDURE, PUBLIC, PASS(obj) :: IsUseFunction => bc_IsUseFunction !! Returns true if the useFunction is true END TYPE AbstractBC_ @@ -170,7 +190,7 @@ END SUBROUTINE bc_CheckEssentialParam INTERFACE MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & & name, idof, nodalValueType, useFunction, isNormal, isTangent, & - & useExternal) + & useExternal, isUserFunction) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: prefix CHARACTER(*), OPTIONAL, INTENT(IN) :: name @@ -180,14 +200,12 @@ MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & !! degree of freedom number !! default is 0 INTEGER(I4B), OPTIONAL, INTENT(IN) :: nodalValueType - !! Space - !! Time - !! SpaceTime - !! Constant + !! Space, Time, SpaceTime, Constant !! default is -1 LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction - !! use fucntion - !! default is false + !! use fucntion; default is false + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isUserFunction + !! set true when userfucntion is used; default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal !! default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTangent @@ -372,7 +390,7 @@ END SUBROUTINE bc_Get INTERFACE MODULE SUBROUTINE bc_GetFEVar(obj, fevar, globalNode, & - & spaceQuadPoints, timeQuadPoints, atime, timeVec) + & spaceQuadPoints, timeQuadPoints, atime, timeVec) CLASS(AbstractBC_), INTENT(IN) :: obj TYPE(FEVariable_), INTENT(INOUT) :: fevar INTEGER(I4B), OPTIONAL, INTENT(IN) :: globalNode(:) @@ -387,6 +405,10 @@ END SUBROUTINE bc_GetFEVar ! GetFromFunction@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get value from function + INTERFACE MODULE SUBROUTINE bc_GetFromFunction(obj, nodeNum, nodalValue, times) CLASS(AbstractBC_), INTENT(IN) :: obj @@ -397,57 +419,45 @@ END SUBROUTINE bc_GetFromFunction END INTERFACE !---------------------------------------------------------------------------- -! GetDOFNo@GetMethods +! GetFromFunction@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. -! date: 2023-02-12 -! summary: Get degree of freedom number +! date: 2023-11-26 +! summary: Get value from function INTERFACE - MODULE PURE FUNCTION bc_GetDOFNo(obj) RESULT(ans) + MODULE SUBROUTINE bc_GetFromUserFunction(obj, nodeNum, nodalValue, times) CLASS(AbstractBC_), INTENT(IN) :: obj - INTEGER(I4B) :: ans - END FUNCTION bc_GetDOFNo + INTEGER(I4B), INTENT(IN) :: nodeNum(:) + REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: nodalValue(:, :) + REAL(DFP), OPTIONAL, INTENT(IN) :: times(:) + END SUBROUTINE bc_GetFromUserFunction END INTERFACE !---------------------------------------------------------------------------- -! isUseFunction@GetMethods +! GetDOFNo@GetMethods !---------------------------------------------------------------------------- -INTERFACE - MODULE PURE FUNCTION bc_IsUseFunction(obj) RESULT(ans) - CLASS(AbstractBC_), INTENT(IN) :: obj - LOGICAL(LGT) :: ans - END FUNCTION bc_IsUseFunction -END INTERFACE - -!---------------------------------------------------------------------------- -! Set@SetMethods -!---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-02-12 +! summary: Get degree of freedom number INTERFACE - MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & - & timeNodalValue, spaceTimeNodalValue, spaceFunction, timeFunction, & - & spaceTimeFunction) - CLASS(AbstractBC_), INTENT(INOUT) :: obj - REAL(DFP), OPTIONAL, INTENT(IN) :: constantNodalValue - REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) - REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) - PROCEDURE(iface_SpaceTimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & spaceTimeFunction - PROCEDURE(iface_SpaceFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & spaceFunction - PROCEDURE(iface_TimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & timeFunction - END SUBROUTINE bc_Set + MODULE PURE FUNCTION bc_GetDOFNo(obj) RESULT(ans) + CLASS(AbstractBC_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION bc_GetDOFNo END INTERFACE !---------------------------------------------------------------------------- ! GetQuery@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Get field values of abstract boundary condition + INTERFACE MODULE PURE SUBROUTINE bc_GetQuery(obj, isInitiated, & & isSelectionByBox, isSelectionByMeshID, isSelectionByElemNum, & @@ -483,4 +493,46 @@ MODULE FUNCTION bc_GetPrefix(obj) RESULT(ans) END FUNCTION bc_GetPrefix END INTERFACE +!---------------------------------------------------------------------------- +! IsUseFunction@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Returns true if useFunction is true + +INTERFACE + MODULE PURE FUNCTION bc_IsUseFunction(obj) RESULT(ans) + CLASS(AbstractBC_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + END FUNCTION bc_IsUseFunction +END INTERFACE + +!---------------------------------------------------------------------------- +! Set@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-26 +! summary: Set fields of abstract boundary condition + +INTERFACE + MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & + & timeNodalValue, spaceTimeNodalValue, spaceFunction, timeFunction, & + & spaceTimeFunction, userFunction) + CLASS(AbstractBC_), INTENT(INOUT) :: obj + REAL(DFP), OPTIONAL, INTENT(IN) :: constantNodalValue + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) + PROCEDURE(iface_SpaceTimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & + & spaceTimeFunction + PROCEDURE(iface_SpaceFunction), POINTER, OPTIONAL, INTENT(IN) :: & + & spaceFunction + PROCEDURE(iface_TimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & + & timeFunction + TYPE(UserFunction_), POINTER, OPTIONAL, INTENT(IN) :: userFunction + END SUBROUTINE bc_Set +END INTERFACE + END MODULE AbstractBC_Class diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 index 352179b99..5a9935f07 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 @@ -31,22 +31,29 @@ obj%idof = 0 obj%nodalValueType = -1 obj%useFunction = .FALSE. +obj%isUserFunction = .FALSE. obj%isNormal = .FALSE. obj%isTangent = .FALSE. obj%useExternal = .FALSE. IF (ALLOCATED(obj%nodalValue)) DEALLOCATE (obj%nodalValue) + +CALL obj%boundary%DEALLOCATE() +IF (ASSOCIATED(obj%dom)) obj%dom => NULL() +IF (ASSOCIATED(obj%func)) THEN + CALL obj%func%DEALLOCATE() +END IF +obj%func => NULL() + IF (ASSOCIATED(obj%SpaceTimeFunction)) obj%SpaceTimeFunction => NULL() IF (ASSOCIATED(obj%SpaceFunction)) obj%SpaceFunction => NULL() IF (ASSOCIATED(obj%TimeFunction)) obj%TimeFunction => NULL() -CALL obj%boundary%DEALLOCATE() -IF (ASSOCIATED(obj%dom)) obj%dom => NULL() END PROCEDURE bc_Deallocate !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_checkessentialparam +MODULE PROCEDURE bc_Checkessentialparam CHARACTER(*), PARAMETER :: myName = "bc_CheckEssentialParam" INTEGER(I4B) :: ii TYPE(String), ALLOCATABLE :: essentialParam(:) @@ -58,7 +65,8 @@ prefix0 = obj%GetPrefix() END IF -astr = "/name/idof/nodalValueType/useFunction/isNormal/isTangent/useExternal" +astr = "/name/idof/nodalValueType/useFunction/isNormal/isTangent/"// & +& "useExternal/isUserFunction" CALL astr%Split(essentialParam, sep="/") CALL CheckEssentialParam(obj=param, & @@ -106,6 +114,9 @@ CALL Set(param, datatype=.TRUE., prefix=prefix, key="useExternal", & & VALUE=input(option=useExternal, default=default_useExternal)) +CALL Set(param, datatype=.TRUE., prefix=prefix, key="isUserFunction", & + & VALUE=input(option=isUserFunction, default=default_useFunction)) + IF (PRESENT(isNormal) .AND. PRESENT(idof)) THEN IF (idof .GT. 0 .AND. isNormal) THEN CALL e%raiseError(modName//'::'//myName//' - '// & @@ -161,6 +172,10 @@ CALL GetValue(obj=param, prefix=prefix%chars(), key="useFunction", & & VALUE=obj%useFunction) +! isUserFunction +CALL GetValue(obj=param, prefix=prefix%chars(), key="isUserFunction", & + & VALUE=obj%isUserFunction) + ! isNormal CALL GetValue(obj=param, prefix=prefix%chars(), key="isNormal", & & VALUE=obj%isNormal) @@ -173,7 +188,7 @@ CALL GetValue(obj=param, prefix=prefix%chars(), key="useExternal", & & VALUE=obj%useExternal) -! check +! Check CALL boundary%GetParam(isSelectionByMeshID=isSelectionByMeshID) abool = boundary%isSelectionByMeshID & & .AND. (.NOT. obj%useFunction) & diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 index 2ae68fc55..d0655c229 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 @@ -40,106 +40,115 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE bc_Get -INTEGER(I4B) :: ii, tsize -CHARACTER(*), PARAMETER :: myName = "bc_Get" +CHARACTER(*), PARAMETER :: myName = "bc_Get()" +INTEGER(I4B) :: ii, tsize, tNodes, tTimes +LOGICAL(LGT) :: isNodalValuePresent, isNOTOK + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Get()') +#endif IF (.NOT. obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'AbstractBC_ object is not initiated, initiate it first.') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: AbstractBC_ object is not initiated'// & + & ', initiate it first.') + RETURN END IF ! get node numbers - IF (.NOT. ASSOCIATED(obj%dom)) THEN - CALL e%raiseError(modName//'::'//myName//' - '// & - & 'AbstractBC_::obj%dom is not associated!') -ELSE - nodeNum = obj%boundary%getNodeNum(domain=obj%dom) + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractBC_::obj%dom is not associated!') + RETURN END IF -! get nodal values - -IF (PRESENT(nodalValue)) THEN - - ! Use function case - - IF (obj%useFunction) THEN - CALL obj%GetFromFunction(nodeNum=nodeNum, & - & nodalValue=nodalValue, times=times) - RETURN - END IF - - IF (.NOT. ALLOCATED(obj%nodalValue)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'nodalValue is not allocated!') - END IF - - ! Getting nodal values +nodeNum = obj%boundary%GetNodeNum(domain=obj%dom) +tNodes = SIZE(nodeNum) - SELECT CASE (obj%nodalValueType) +tTimes = 1 +IF (PRESENT(times)) tTimes = SIZE(times) - ! Constant +isNodalValuePresent = PRESENT(nodalValue) - CASE (CONSTANT) - - IF (PRESENT(times)) THEN - CALL Reallocate(nodalValue, SIZE(nodeNum), SIZE(times)) - ELSE - CALL Reallocate(nodalValue, SIZE(nodeNum), 1) - END IF +IF (isNodalValuePresent .AND. obj%useFunction) THEN + CALL obj%GetFromFunction(nodeNum=nodeNum, nodalValue=nodalValue, & + & times=times) + RETURN +END IF - nodalValue = obj%nodalValue(1, 1) +IF (isNodalValuePresent .AND. obj%isUserFunction) THEN + CALL obj%GetFromUserFunction(nodeNum=nodeNum, nodalValue=nodalValue, & + & times=times) + RETURN +END IF - ! Space +isNOTOK = isNodalValuePresent .AND. (.NOT. ALLOCATED(obj%nodalValue)) - CASE (SPACE) +IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: AbstractBC_::obj%nodalValue is not allocated!') + RETURN +END IF - IF (SIZE(obj%nodalValue, 1) .NE. SIZE(nodeNum)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'SIZE( obj%nodalValue, 1 ) .NE. SIZE( nodeNum )') - END IF +IF (.NOT. isNodalValuePresent) RETURN - nodalValue = obj%nodalValue +! get nodal values +SELECT CASE (obj%nodalValueType) - ! Time +! Constant +CASE (CONSTANT) + CALL Reallocate(nodalValue, tNodes, tTimes) + nodalValue = obj%nodalValue(1, 1) + +! Space +CASE (SPACE) + isNOTOK = SIZE(obj%nodalValue, 1) .NE. SIZE(nodeNum) + IF (isNOTOK) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: SIZE( obj%nodalValue, 1 ) .NE. SIZE( nodeNum )') + RETURN + END IF - CASE (TIME) + nodalValue = obj%nodalValue - tsize = SIZE(obj%nodalValue, 1) - IF (PRESENT(times)) THEN - IF (tsize .NE. SIZE(times)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'SIZE( obj%nodalValue, 2 ) .NE. SIZE( times )') - END IF +! Time +CASE (TIME) + tsize = SIZE(obj%nodalValue, 1) + IF (PRESENT(times)) THEN + IF (tsize .NE. SIZE(times)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: SIZE( obj%nodalValue, 2 ) .NE. SIZE( times )') END IF + END IF - CALL Reallocate(nodalValue, SIZE(nodeNum), tsize) - - DO ii = 1, tsize - nodalValue(:, ii) = obj%nodalValue(ii, 1) - END DO - - ! SpaceTime + CALL Reallocate(nodalValue, SIZE(nodeNum), tsize) - CASE (SpaceTime) + DO ii = 1, tsize + nodalValue(:, ii) = obj%nodalValue(ii, 1) + END DO - IF (SIZE(obj%nodalValue, 1) .NE. SIZE(nodeNum)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'SIZE( obj%nodalValue, 1 ) .NE. SIZE( nodeNum )') - END IF +! SpaceTime +CASE (SpaceTime) + IF (SIZE(obj%nodalValue, 1) .NE. SIZE(nodeNum)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: SIZE( obj%nodalValue, 1 ) .NE. SIZE( nodeNum )') + END IF - IF (PRESENT(times)) THEN - IF (SIZE(obj%nodalValue, 2) .NE. SIZE(times)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & 'SIZE( obj%nodalValue, 2 ) .NE. SIZE( times )') - END IF + IF (PRESENT(times)) THEN + IF (SIZE(obj%nodalValue, 2) .NE. SIZE(times)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: SIZE( obj%nodalValue, 2 ) .NE. SIZE( times )') END IF + END IF - nodalValue = obj%nodalValue - - END SELECT -END IF + nodalValue = obj%nodalValue +END SELECT +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Get()') +#endif END PROCEDURE bc_Get !---------------------------------------------------------------------------- @@ -175,12 +184,11 @@ SELECT CASE (obj%nodalValueType) - ! space function - +! Space CASE (Space) IF (.NOT. ASSOCIATED(obj%SpaceFunction)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & "When nodalValueType is & & Space and useFunction is specified, & & then SpaceFunction is needed, & @@ -194,12 +202,11 @@ & x=xij(:, obj%dom%getLocalNodeNumber(globalNode=nodeNum(ii)))) END DO - ! Time - +! Time CASE (Time) IF (.NOT. ASSOCIATED(obj%TimeFunction)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & "When nodalValueType is Time & & and useFunction is specified, & & then TimeFunction is needed, & @@ -207,7 +214,7 @@ END IF IF (.NOT. PRESENT(times)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & "When `nodalValueType` is Time & & and `useFunction` is TRUE, & & then `times` is needed in the passing argument, & @@ -220,12 +227,11 @@ nodalValue(:, ii) = obj%TimeFunction(t=times(ii)) END DO - ! SpaceTime - +! SpaceTime CASE (SpaceTime) IF (.NOT. ASSOCIATED(obj%SpaceTimeFunction)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & "When `nodalValueType` is `SpaceTime` and & & `useFunction` is specified, & & then `SpaceTimeFunction` is needed, & @@ -233,7 +239,7 @@ END IF IF (.NOT. PRESENT(times)) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & + CALL e%RaiseError(modName//'::'//myName//" - "// & & "When `nodalValueType` is `SpaceTime` & & and `useFunction` is True, & & then `times` is needed as argument, & @@ -295,4 +301,119 @@ & '[WIP ERROR] :: This routine should be implemented by child class.') END PROCEDURE bc_GetPrefix +!---------------------------------------------------------------------------- +! GetFromUserFunction +!---------------------------------------------------------------------------- + +MODULE PROCEDURE bc_GetFromUserFunction +CHARACTER(*), PARAMETER :: myName = "bc_GetFromUserFunction()" +INTEGER(I4B) :: ii, kk, retType, tNodes, nsd, tTimes +REAL(DFP) :: xij(4, 1), ans +LOGICAL(LGT) :: problem + +! get pointer to nodecoord + +IF (.NOT. ASSOCIATED(obj%func)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[INTERNAL ERROR] :: When nodalValueType is "// & + & CHAR_LF//"Space and useFunction is specified, "// & + & CHAR_LF//"then SpaceFunction is needed, "// & + & CHAR_LF//"but it is not associated") + RETURN +END IF + +retType = obj%func%GetReturnType() + +IF (retType .NE. Scalar) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Return type of user function should be '// & + & 'scalar.') + RETURN +END IF + +problem = (obj%nodalValueType .EQ. Time) .AND. (.NOT. PRESENT(times)) +IF (problem) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[INTERNAL ERROR] :: When `nodalValueType` is Time "// & + & " and `IsUserFunction` is TRUE, "// & + & " then `times` is needed in the passing argument,"// & + & " but it is not present") + RETURN +END IF + +problem = (obj%nodalValueType .EQ. SpaceTime) .AND. (.NOT. PRESENT(times)) +IF (problem) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[INTERNAL ERROR] :: When `nodalValueType` is SpaceTime "// & + & " and `IsUserFunction` is TRUE, "// & + & " then `times` is needed in the passing argument,"// & + & " but it is not present") + RETURN +END IF + +tNodes = SIZE(nodeNum) +nsd = obj%dom%GetNSD() + +SELECT CASE (obj%nodalValueType) + +! Constant +CASE (Constant) + CALL Reallocate(nodalValue, tNodes, 1) + + CALL obj%dom%GetNodeCoord(nodeCoord=xij(1:nsd, 1:1), & + & globalNode=nodeNum(1:1)) + + CALL obj%func%Get(val=ans, args=xij(1:nsd, 1)) + + nodalValue(:, 1) = ans + +! Space +CASE (Space) + CALL Reallocate(nodalValue, tNodes, 1) + + DO ii = 1, tNodes + CALL obj%dom%GetNodeCoord(nodeCoord=xij(1:nsd, 1:1), & + & globalNode=nodeNum(ii:ii)) + + CALL obj%func%Get(val=ans, args=xij(1:nsd, 1)) + + nodalValue(ii, 1) = ans + END DO + +! Time +CASE (Time) + + tTimes = SIZE(times) + + CALL Reallocate(nodalValue, tNodes, tTimes) + + DO ii = 1, tTimes + CALL obj%func%Get(val=ans, args=times(ii:ii)) + + nodalValue(:, ii) = ans + END DO + +! SpaceTime +CASE (SpaceTime) + tTimes = SIZE(times) + + CALL Reallocate(nodalValue, tNodes, tTimes) + + DO kk = 1, tTimes + xij(nsd + 1, 1) = times(kk) + + DO ii = 1, tNodes + CALL obj%dom%GetNodeCoord(nodeCoord=xij(1:nsd, 1:1), & + & globalNode=nodeNum(ii:ii)) + + CALL obj%func%Get(val=ans, args=xij(1:nsd + 1, 1)) + + nodalValue(ii, kk) = ans + END DO + END DO + +END SELECT + +END PROCEDURE bc_GetFromUserFunction + END SUBMODULE GetMethods diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 index 12f6c0d24..8e19a1348 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 @@ -37,53 +37,57 @@ REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//"::"//myName//" - "// & + & "[START] Import()") +#endif + IF (obj%isInitiated) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The object is already initiated, deallocate first!') + & '[INTERNAL ERROR] :: AbstractBC_::obj is already initiated'// & + & ', deallocate first') + RETURN END IF obj%isInitiated = .TRUE. obj%dom => dom -CALL e%RaiseInformation(modName//"::"//myName//" - "// & -& "Importing Boundary condition") - IF (.NOT. hdf5%isOpen()) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') + & '[INTERNAL ERROR] :: HDF5 file is not opened') + RETURN END IF IF (.NOT. hdf5%isRead()) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have read permission') + & '[INTERNAL ERROR] :: HDF5 file does not have read permission') + RETURN END IF dsetname = TRIM(group)//"/name" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The dataset name should be present') + & '[INTERNAL ERROR] :: The dataset name should be present') ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=obj%name) + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%name) END IF dsetname = TRIM(group)//"/idof" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The dataset idof should be present') + & '[INTERNAL ERROR] :: The dataset idof should be present') ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=obj%idof) + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%idof) END IF dsetname = TRIM(group)//"/nodalValueType" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The dataset nodalValueType should be present') + & '[INTERNAL ERROR] :: The dataset nodalValueType should be present') ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=strval) + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) END IF -SELECT CASE (TRIM(strval%chars())) + +SELECT CASE (strval%chars()) CASE ("CONSTANT") obj%nodalValueType = Constant CASE ("SPACE") @@ -94,13 +98,26 @@ obj%nodalValueType = SpaceTime END SELECT +dsetname = TRIM(group)//"/isUserFunction" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset isUserFunction should be present') +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%isUserFunction) +END IF + +IF (obj%isUserFunction) THEN + ALLOCATE (obj%func) + CALL obj%func%IMPORT(hdf5=hdf5, & + & group=TRIM(group)//"/userFunction") +END IF + dsetname = TRIM(group)//"/useFunction" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset useFunction should be present') ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=obj%useFunction) + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%useFunction) END IF dsetname = TRIM(group)//"/useExternal" @@ -108,11 +125,10 @@ CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset useExternal should be present') ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=obj%useExternal) + CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%useExternal) END IF -dsetname = TRIM(group)//"/Boundary" +dsetname = TRIM(group)//"/boundary" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & & 'The dataset Boundary, which is a group, should be present') @@ -120,32 +136,34 @@ CALL obj%boundary%IMPORT(hdf5=hdf5, group=dsetname%chars()) END IF -IF (.NOT. obj%UseFunction) THEN - dsetname = TRIM(group)//"/NodalValue" +IF (.NOT. obj%useFunction) THEN + dsetname = TRIM(group)//"/nodalValue" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The dataset NodalValue should be present') + & 'The dataset nodalValue should be present') END IF SELECT CASE (obj%nodalValueType) CASE (Constant) - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=real0) - CALL Reallocate(obj%NodalValue, 1, 1) - obj%NodalValue = real0 + CALL hdf5%READ(dsetname=dsetname%chars(), vals=real0) + CALL Reallocate(obj%nodalValue, 1, 1) + obj%nodalValue = real0 CASE (Space, Time) - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=real1) + CALL hdf5%READ(dsetname=dsetname%chars(), vals=real1) CALL Reallocate(obj%nodalValue, SIZE(real1), 1) - obj%NodalValue(:, 1) = real1 + obj%nodalValue(:, 1) = real1 CASE (SpaceTime) - CALL hdf5%READ(dsetname=dsetname%chars(), & - & vals=real2) - obj%NodalValue = real2 + CALL hdf5%READ(dsetname=dsetname%chars(), vals=real2) + obj%nodalValue = real2 END SELECT END IF IF (ALLOCATED(real1)) DEALLOCATE (real1) IF (ALLOCATED(real2)) DEALLOCATE (real2) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif END PROCEDURE bc_Import !---------------------------------------------------------------------------- @@ -158,33 +176,36 @@ REAL(DFP) :: real0 REAL(DFP), ALLOCATABLE :: real1(:), real2(:, :) +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + IF (.NOT. obj%isInitiated) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The object is not initiated, initiate it first!') + & '[INTERNAL ERROR] :: The object is not initiated, initiate it first!') + RETURN END IF -CALL e%RaiseInformation(modName//"::"//myName//" - "// & - & "Exporting Dirichlet Boundary Condition") - IF (.NOT. hdf5%isOpen()) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'HDF5 file is not opened') + & '[INTERNAL ERROR] :: HDF5 file is not opened') + RETURN END IF IF (.NOT. hdf5%isWrite()) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'HDF5 file does not have write permission') + & '[INTERNAL ERROR] :: HDF5 file does not have write permission') + RETURN END IF ! WRITE name dsetname = TRIM(group)//"/name" -CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=obj%name) +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%name) ! WRITE idof dsetname = TRIM(group)//"/idof" -CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=obj%idof) +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%idof) ! WRITE nodalValueType dsetname = TRIM(group)//"/nodalValueType" @@ -198,44 +219,43 @@ CASE (SpaceTime) strval = "SPACETIME" END SELECT -CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=strval) +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) ! WRITE useFunction dsetname = TRIM(group)//"/useFunction" -CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=obj%useFunction) +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%useFunction) ! WRITE useExternal dsetname = TRIM(group)//"/useExternal" -CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=obj%useExternal) +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%useExternal) ! WRITE Boundary -dsetname = TRIM(group)//"/Boundary" +dsetname = TRIM(group)//"/boundary" CALL obj%boundary%export(hdf5=hdf5, group=dsetname%chars()) ! Read nodalValue IF (.NOT. obj%UseFunction) THEN - dsetname = TRIM(group)//"/NodalValue" - IF (.NOT. ALLOCATED(obj%NodalValue)) THEN + + dsetname = TRIM(group)//"/nodalValue" + IF (.NOT. ALLOCATED(obj%nodalValue)) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'NodalValue is not allocated, it seems NodalValue is not set') + & '[INTERNAL ERROR] :: nodalValue is not allocated, '// & + & 'it seems nodalValue is not set') + RETURN END IF + SELECT CASE (obj%nodalValueType) CASE (Constant) - real0 = obj%NodalValue(1, 1) - CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=real0) + real0 = obj%nodalValue(1, 1) + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=real0) CASE (Space, Time) - real1 = obj%NodalValue(:, 1) - CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=real1) + real1 = obj%nodalValue(:, 1) + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=real1) CASE (SpaceTime) - real2 = obj%NodalValue - CALL hdf5%WRITE(dsetname=dsetname%chars(), & - & vals=real2) + real2 = obj%nodalValue + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=real2) END SELECT + END IF IF (ALLOCATED(real1)) DEALLOCATE (real1) @@ -255,10 +275,11 @@ IF (.NOT. obj%isInitiated) THEN CALL Display("AbstractBC_::obj is not initiated, nothing to display", & & unitNo=unitNo) + RETURN END IF -CALL Display("# name : "//TRIM(obj%name%chars()), unitNo=unitNo) -CALL Display(obj%idof, "# idof : ", unitNo=unitNo) +CALL Display("name : "//TRIM(obj%name%chars()), unitNo=unitNo) +CALL Display(obj%idof, "idof : ", unitNo=unitNo) SELECT CASE (obj%nodalValueType) CASE (Constant) @@ -270,32 +291,42 @@ CASE (SpaceTime) strval = "SPACETIME" END SELECT -CALL Display("# nodalValueType : "//TRIM(strval%chars()), unitNo=unitNo) +CALL Display("nodalValueType : "//TRIM(strval%chars()), unitNo=unitNo) +CALL Display(obj%isUserFunction, "isUserFunction : ", unitNo=unitNo) CALL Display(obj%useFunction, "useFunction : ", unitNo=unitNo) CALL Display(obj%useExternal, "useExternal : ", unitNo=unitNo) CALL obj%Boundary%Display(msg="Boundary : ", unitNo=unitNo) IF (.NOT. obj%UseFunction) THEN - IF (.NOT. ALLOCATED(obj%NodalValue)) THEN - CALL Display("NodalValue : NOT ALLOCATED", unitNo=unitNo) + IF (.NOT. ALLOCATED(obj%nodalValue)) THEN + CALL Display("nodalValue : NOT ALLOCATED", unitNo=unitNo) ELSE SELECT CASE (obj%nodalValueType) CASE (Constant) - real0 = obj%NodalValue(1, 1) - CALL Display(real0, "NodalValue : ", unitNo=unitNo) + real0 = obj%nodalValue(1, 1) + CALL Display(real0, "nodalValue : ", unitNo=unitNo) CASE (Space, Time) - real1 = obj%NodalValue(:, 1) - CALL Display(real1, "NodalValue : ", unitNo=unitNo, orient="col") + real1 = obj%nodalValue(:, 1) + CALL Display(real1, "nodalValue : ", unitNo=unitNo, orient="col") CASE (SpaceTime) - real2 = obj%NodalValue(:, :) - CALL Display(real2, "NodalValue : ", unitNo=unitNo) + real2 = obj%nodalValue(:, :) + CALL Display(real2, "nodalValue : ", unitNo=unitNo) END SELECT END IF END IF +IF (obj%isUserFunction) THEN + IF (ASSOCIATED(obj%func)) THEN + CALL obj%func%Display("userFunction", unitNo=unitNo) + ELSE + CALL Display("userFunction :: NOT ASSOCIATEDS", unitNo=unitNo) + END IF +END IF + IF (ALLOCATED(real1)) DEALLOCATE (real1) IF (ALLOCATED(real2)) DEALLOCATE (real2) + END PROCEDURE bc_Display !---------------------------------------------------------------------------- @@ -305,7 +336,8 @@ MODULE PROCEDURE bc_ImportParamFromToml CHARACTER(*), PARAMETER :: myName = "bc_ImportParamFromToml()" INTEGER(I4B) :: origin, stat, nodalValueType, idof -LOGICAL(LGT) :: useFunction, isNormal, isTangent, useExternal +LOGICAL(LGT) :: useFunction, isNormal, isTangent, useExternal, & +& isUserFunction TYPE(String) :: nodalValueType_string, name, astr #ifdef DEBUG_VER @@ -316,6 +348,9 @@ CALL toml_get(table, "useFunction", useFunction, & & default_useFunction, origin=origin, stat=stat) +CALL toml_get(table, "isUserFunction", isUserFunction, & + & default_useFunction, origin=origin, stat=stat) + CALL toml_get(table, "isTangent", isTangent, & & default_isTangent, origin=origin, stat=stat) @@ -355,6 +390,7 @@ & idof=idof, & & nodalValueType=nodalValueType, & & useFunction=useFunction, & + & isUserFunction=isUserFunction, & & isNormal=isNormal, & & isTangent=isTangent, & & useExternal=useExternal & @@ -404,6 +440,22 @@ CALL boundary%ImportFromToml(table=node, dom=dom) CALL obj%Initiate(param=param, boundary=boundary, dom=dom) +IF (obj%isUserFunction) THEN + node => NULL() + CALL toml_get(table, "function", node, origin=origin, requested=.FALSE., & + & stat=stat) + + IF (.NOT. ASSOCIATED(node)) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: following error occured while reading '// & + & 'the toml file :: cannot find [function] table in config.') + RETURN + END IF + + ALLOCATE (obj%func) + CALL obj%func%ImportFromToml(table=node) +END IF + IF (obj%useFunction) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[WIP ERROR] :: useFunction = .TRUE., currently you cannot '// & @@ -420,7 +472,7 @@ & 'value should be a constant (scalar real value).') RETURN END IF - CALL obj%Set(constantNodalValue=constantValue) + CALL obj%Set(constantnodalValue=constantValue) CASE (Space, Time) CALL GetValue(table=table, key="value", VALUE=value_r1, & @@ -439,9 +491,9 @@ END IF IF (obj%nodalValueType .EQ. Space) THEN - CALL obj%Set(spaceNodalValue=value_r1) + CALL obj%Set(spacenodalValue=value_r1) ELSE - CALL obj%Set(timeNodalValue=value_r1) + CALL obj%Set(timenodalValue=value_r1) END IF CASE (SpaceTime) @@ -460,7 +512,7 @@ RETURN END IF - CALL obj%Set(spaceTimeNodalValue=value_r2) + CALL obj%Set(spaceTimenodalValue=value_r2) END SELECT diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 index 1890a40b1..83baba28b 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 @@ -24,10 +24,15 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_set -CHARACTER(*), PARAMETER :: myName = "bc_set" +MODULE PROCEDURE bc_Set +CHARACTER(*), PARAMETER :: myName = "bc_Set" LOGICAL(LGT) :: notFunc_notExt, isTimeFunc, isSpaceFunc, isSTFunc, isFunc, & - & isConstVal, isSpaceVal, isSTVal, isTimeVal, bool1, bool2 + & isConstVal, isSpaceVal, isSTVal, isTimeVal, bool1, bool2, isUserFunction + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Set()') +#endif IF (.NOT. obj%isInitiated) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & @@ -37,6 +42,7 @@ notFunc_notExt = (.NOT. obj%useFunction) .AND. & & (.NOT. obj%useExternal) +isUserFunction = PRESENT(userFunction) isTimeFunc = PRESENT(timeFunction) isSpaceFunc = PRESENT(spaceFunction) isSTFunc = PRESENT(spaceTimeFunction) @@ -120,14 +126,27 @@ RETURN END IF +! userFunction +bool1 = isUserFunction .AND. obj%isUserFunction +IF (.NOT. bool1) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: AbstractBC_::obj is not correctly initiated"// & + & " for userFunction") + RETURN +END IF + +IF (isUserFunction) THEN + obj%func => userFunction + RETURN +END IF + ! spaceFunction bool1 = isSpaceFunc .AND. (obj%nodalValueType .NE. Space) IF (bool1) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & & "with nodalValueType=Space"// & - & CHAR_LF// & - & 'So, spaceFunction cannot be present') + & CHAR_LF//'So, spaceFunction cannot be present') RETURN END IF @@ -178,6 +197,11 @@ RETURN END IF -END PROCEDURE bc_set +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Set()') +#endif + +END PROCEDURE bc_Set END SUBMODULE SetMethods From feba525c0ab5fcb1574b6302c25e259ba603bf31 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 23:50:42 +0900 Subject: [PATCH 064/117] Adding drprint.json Adding dprint.json for markdown and toml config. --- dprint.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 dprint.json diff --git a/dprint.json b/dprint.json new file mode 100644 index 000000000..515a97c01 --- /dev/null +++ b/dprint.json @@ -0,0 +1,11 @@ +{ + "markdown": { + }, + "toml": { + }, + "excludes": [], + "plugins": [ + "https://plugins.dprint.dev/markdown-0.16.3.wasm", + "https://plugins.dprint.dev/toml-0.5.4.wasm" + ] +} From 7cd9b8e46c4baea95a6f2b2f68052c9bb823716a Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 23:50:59 +0900 Subject: [PATCH 065/117] Update AbstractBC.toml Adding AbstractBC.toml --- src/modules/AbstractBC/src/AbstractBC.toml | 174 +++++++++++++++------ 1 file changed, 130 insertions(+), 44 deletions(-) diff --git a/src/modules/AbstractBC/src/AbstractBC.toml b/src/modules/AbstractBC/src/AbstractBC.toml index 5d7f409b5..2c145a184 100644 --- a/src/modules/AbstractBC/src/AbstractBC.toml +++ b/src/modules/AbstractBC/src/AbstractBC.toml @@ -1,61 +1,147 @@ [bc] -name="DirichletBC" -idof=1 -nodalValueType="Constant" # Time, SpaceTime, Space -useFunction=false -isNormal=false -isTangent=false -useExternal=false -value=20.0 # when nodalValueType=Constant -# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Space -# value=[1.0, 2.0, 3.0, 4.0] # when nodalValueType=Time -# value=[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]] # SpaceTime -spaceFunction="lua script f(x)" -timeFunction="lua script f(t)" -spaceTimeFunction="lua script f(x, t)" +name = "DirichletBC" +# Name of the boundary condition +idof = 1 +# idof denotes the degree of freedom where +# we apply the contraint, +# For x component idof is 1 +# For y component idof is 2 +# For z component idof is 3 + +nodalValueType = "Constant" # Time, SpaceTime, Space +# Other option: Constant, Time, Space, SpaceTime +# nodalValuetype denotes the type of boundary condition +# It can take following values +# Constant: It means the boundary condition is constant in +# space and time. +# Space: It means the boundary condition is variable in +# space but constant in time. +# Time: It means the boundary condition is variable in +# in time but constant in Space +# SpaceTime:It means the boundary condition is variable in +# both space and time. + +value = 20.0 +# Value of boundary condition +# The shape of value depends upon the nodalValueType as explained below. +# For nodalValueType="Constant", value should be a scalar real value +# For nodalValueType="Space", value should be a vector of real values +# value=[1.0, 2.0, 3.0, 4.0] +# For nodalValueType="Time", value should be a vector of real values +# value=[1.0, 2.0, 3.0, 4.0] +# For nodalValueType="SpaceTime", value should be two dimensional array of +# real values +# value=[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]] + +isUserFunction = false +isNormal = false +isTangent = false +useExternal = false + +[bc.function] +name = "boundaryFunction" +# name of the function + +returnType = "Scalar" +# returnType must be "Scalar" + +numReturns = 1 +# number of returns must be 1 + +argType = "Space" +# argumen type of function, It can take following values +# "Constant", when the user function is constant +# "Space", when the user function is space dependent only. +# "Time", when the user function is time dependent only. +# "SpaceTime", when the user function is space-time dependent. + +numArgs = 3 +# number of arguments +# number of arguments should be 0, when argType is "Constant" +# number of arguments should be 1, when argType is "Time" +# number of arguments should be 3, when argType is "Space" +# number of arguments should be 4, when argType is "SpaceTime" + +scalarValue = 1.0 +# if lua script and luaFunctionName are absent then this +# variable must be given. +# When this is given, then argType must be Constant, and +# numArgs should be 0. + +luaScript = "./hello.lua" +# name of the lua script which contains the functions + +luaFunctionName = "hello" +# which function in the lua script to be used for boundary condition [bc.boundary] isSelectionByMeshID = false -isSelectionByElemNum = false -isSelectionByBox = false -isSelectionByNodeNum = false - +# set isSelectionByMeshID to true when mesh selection is by meshID +# if this variable is set to true then we should provide following +# table [bc.boundary.meshID] -point = [1,2,3] # "filename.txt" -line = [1,2,3,4] # "filename.txt" -surface = [1,2,3] # "filename.txt" -volume = [1,2,3] # "filename.txt" +point = [1, 2, 3] +# id of mesh of points +# you can also give the filename +line = [1, 2, 3, 4] +# id of mesh of lines +# you can also give the filename +surface = [1, 2, 3] +# id of mesh of surfaces +# you can also give the filename "filename.txt" +volume = [1, 2, 3] +# id of mesh of volumes +# you can also give the filename "filename.txt" + +isSelectionByElemNum = false +# set isSelectionByElemNum to true when mesh selection is by +# specifying element number +# if this variable is set to true then we should provide following +# table +[bc.boundary.elemNum] +point = [1, 2, 3] +# element number for points +line = [1, 2, 3] +# element number of lines +surface = [1, 2, 3] +# element number of surfaces +volume = [1, 2, 3] +# element number of volume +isSelectionByBox = false +# set isSelectionByBox to true when mesh selection is by +# specifying the bounding boxes +# if this variable is set to true then we should provide following +# table [bc.boundary.box] point = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 0.0, zmax = 1.0 }, + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 2.0, zmax = 3.0 }, ] - +# boxes for mesh of points line = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 0.0, zmax = 1.0 }, + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 2.0, zmax = 3.0 }, ] - +# boxes for mesh of lines surface = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 0.0, zmax = 1.0 }, + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 2.0, zmax = 3.0 }, ] - +# boxes for mesh of surfaces volume = [ -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=0.0, zmax=1.0}, -{xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, zmin=2.0, zmax=3.0} + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 0.0, zmax = 1.0 }, + { xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 2.0, zmax = 3.0 }, ] +# boxes for mesh of volumes -[bc.boundary.elemNum] -point = [1,2,3] -line = [1,2,3] -surface=[1,2,3] -volume=[1,2,3] - +isSelectionByNodeNum = false +# set isSelectionByNodeNum to true when mesh selection is by +# by specifying the node number. +# if this variable is set to true then we should provide following +# table [bc.boundary.nodeNum] -point = [1,2,3] -line = [1,2,3] -surface=[1,2,3] -volume=[1,2,3] - +point = [1, 2, 3] +line = [1, 2, 3] +surface = [1, 2, 3] +volume = [1, 2, 3] From 1715058ef5fedeb25ffbb9cface0c4a49a4db5bd Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 23:51:16 +0900 Subject: [PATCH 066/117] Update UseFunction.toml Adding UseFunction.toml --- src/modules/UserFunction/src/UseFunction.toml | 60 +++++++++++++++---- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/src/modules/UserFunction/src/UseFunction.toml b/src/modules/UserFunction/src/UseFunction.toml index eae18f084..b0b83fdc6 100644 --- a/src/modules/UserFunction/src/UseFunction.toml +++ b/src/modules/UserFunction/src/UseFunction.toml @@ -1,16 +1,56 @@ [userFunction] +name = "boundaryFunction" +# name of the function + returnType = "Scalar" -# returnType = "Vector" -# returnType = "Matrix" +# Return type of function, it can take following values +# "Scalar" +# "Vector" +# "Matrix" + +numReturns = 1 +# number of returns, its value depends upon the returnType +# It is 1, when returnType is "Scalar" +# It is 3, when returnType is "Vector" +# It is 9, when returnType is "Matrix" + argType = "Space" -# argType = "Constant" -# argType = "Space" -# argType = "Time" -# argType = "SpaceTime" +# argumen type of function, It can take following values +# "Constant", when the user function is constant +# "Space", when the user function is space dependent only. +# "Time", when the user function is time dependent only. +# "SpaceTime", when the user function is space-time dependent. + numArgs = 3 -numReturns = 1 -luaScript = "./hello.lua" -luaFunctionName="hello" -scalarValue = 1.0 +# number of arguments +# number of arguments should be 0, when argType is "Constant" +# number of arguments should be 1, when argType is "Time" +# number of arguments should be 3, when argType is "Space" +# number of arguments should be 4, when argType is "SpaceTime" + +scalarValue = 1.0 +# if lua script and luaFunctionName are absent then this +# variable must be given. +# When this is given, then argType must be Constant, and +# numArgs should be 0. + vectorValue = [1.0, 2.0, 3.0] +# if lua script and luaFunctionName are absent then this +# variable must be given. +# When this is given, then +# - returnType must be Vector +# - number of returns must 3 +# - argType must be Constant, and +# - numArgs should be 0. + matrixValue = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]] +# if lua script and luaFunctionName are absent then this +# variable must be given. +# When this is given, then +# - returnType must be Matrix +# - number of returns must 9 +# - argType must be Constant, and +# - numArgs should be 0. +# In this case returnShape must be given + +returnShape = [3, 3] From 2108baa7842abbe1d4f5b83149a1430389fe2692 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 23:52:18 +0900 Subject: [PATCH 067/117] Update UserFunction_Class@IOMethods.F90 Updating ImportFromToml routine. --- .../src/UserFunction_Class@IOMethods.F90 | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 b/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 index b82825ab7..7c0557966 100644 --- a/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 +++ b/src/submodules/UserFunction/src/UserFunction_Class@IOMethods.F90 @@ -346,19 +346,47 @@ CALL toml_get(table, "numArgs", numArgs, origin=origin, stat=stat) bool1 = stat .NE. toml_stat%success IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: numArgs should be present, and '// & - & 'it is a scalar integer number.') - RETURN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'If numArgs should not present, '// & + & 'the default values are used') + + SELECT CASE (argType) + CASE (Constant) + numArgs = DEFAULT_NUM_ARG_CONSTANT + CASE (Space) + numArgs = DEFAULT_NUM_ARG_SPACE + CASE (Time) + numArgs = DEFAULT_NUM_ARG_TIME + CASE (SpaceTime) + numArgs = DEFAULT_NUM_ARG_SPACETIME + CASE default + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[Config Error]:: No case found for argType') + RETURN + END SELECT END IF CALL toml_get(table, "numReturns", numReturns, origin=origin, stat=stat) bool1 = stat .NE. toml_stat%success IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: numReturns should be present, and '// & - & 'it is a scalar integer number.') - RETURN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'numReturns should is not present, and '// & + & 'using default value for numReturns.') + + SELECT CASE (returnType) + CASE (Scalar) + numReturns = DEFAULT_NUM_ARG_SCALAR + CASE (Vector) + numReturns = DEFAULT_NUM_ARG_VECTOR + CASE (Matrix) + numReturns = DEFAULT_NUM_ARG_MATRIX + CASE default + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[CONFIG ERROR] :: no case found for returnType, and '// & + & 'numReturns should be present, and '// & + & 'it is a scalar integer number.') + RETURN + END SELECT END IF CALL toml_get(table, "luaScript", luaScript%raw, origin=origin, stat=stat) @@ -426,19 +454,19 @@ IF (.NOT. obj%isLuaScript) THEN SELECT CASE (obj%returnType) CASE (Scalar) - CALL toml_get(table, "scalarValue", scalarValue, & + CALL toml_get(table, "value", scalarValue, & & origin=origin, stat=stat) IF (stat .NE. toml_stat%success) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: returnType is Scalar, and '// & & CHAR_LF//'argType is Constant. '// & - & CHAR_LF//'Therefore, scalarValue should be present.') + & CHAR_LF//'Therefore, value should be present.') RETURN END IF CALL obj%Set(scalarValue=scalarValue) CASE (Vector) - CALL GetValue(table=table, key="vectorValue", & + CALL GetValue(table=table, key="value", & & VALUE=vectorValue, origin=origin, stat=stat, isFound=isFound) bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) @@ -446,7 +474,7 @@ CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: returnType is Vector, and '// & & CHAR_LF//'argType is Constant. '// & - & CHAR_LF//'Therefore, vectorValue should be present.') + & CHAR_LF//'Therefore, value should be present.') RETURN END IF @@ -454,7 +482,7 @@ IF (ALLOCATED(vectorValue)) DEALLOCATE (vectorValue) CASE (Matrix) - CALL GetValue(table=table, key="matrixValue", & + CALL GetValue(table=table, key="value", & & VALUE=matrixValue, origin=origin, stat=stat, isFound=isFound) bool1 = (.NOT. isFound) .OR. (stat .NE. toml_stat%success) @@ -462,7 +490,7 @@ CALL e%RaiseError(modName//'::'//myName//' - '// & & '[CONFIG ERROR] :: returnType is Matrix, and '// & & CHAR_LF//'argType is Constant. '// & - & CHAR_LF//'Therefore, matrixValue should be present.') + & CHAR_LF//'Therefore, value should be present.') RETURN END IF From 0e1d501c0d04c46cdf6aa54cb8711aeafb5c98e9 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Tue, 28 Nov 2023 23:53:00 +0900 Subject: [PATCH 068/117] Adding UserFuncion in AbstractBC Adding UserFunction in AbstractBC. Fixes issue #205 --- .../AbstractBC/src/AbstractBC_Class.F90 | 51 +------- .../AbstractBC_Class@ConstructorMethods.F90 | 26 ++-- .../src/AbstractBC_Class@GetMethods.F90 | 111 +----------------- .../src/AbstractBC_Class@IOMethods.F90 | 59 ++++------ .../src/AbstractBC_Class@SetMethods.F90 | 74 +----------- 5 files changed, 52 insertions(+), 269 deletions(-) diff --git a/src/modules/AbstractBC/src/AbstractBC_Class.F90 b/src/modules/AbstractBC/src/AbstractBC_Class.F90 index dd7b14511..8aa711571 100644 --- a/src/modules/AbstractBC/src/AbstractBC_Class.F90 +++ b/src/modules/AbstractBC/src/AbstractBC_Class.F90 @@ -30,10 +30,9 @@ MODULE AbstractBC_Class PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractBC_Class" CHARACTER(*), PARAMETER :: default_name = "AbstractBC" -INTEGER(I4B), PARAMETER :: default_idof = 0_I4B -INTEGER(I4B), PARAMETER :: default_nodalValueType = -1_I4B +INTEGER(I4B), PARAMETER :: default_idof = 1_I4B +INTEGER(I4B), PARAMETER :: default_nodalValueType = Constant CHARACTER(*), PARAMETER :: default_nodalValueType_char = "NONE" -LOGICAL(LGT), PARAMETER :: default_useFunction = .FALSE. LOGICAL(LGT), PARAMETER :: default_isUserFunction = .FALSE. LOGICAL(LGT), PARAMETER :: default_isNormal = .FALSE. LOGICAL(LGT), PARAMETER :: default_isTangent = .FALSE. @@ -65,8 +64,6 @@ MODULE AbstractBC_Class !! degree of freedom number INTEGER(I4B) :: nodalValueType = default_nodalValueType !! Constant, Space, SpaceTime, Time - LOGICAL(LGT) :: useFunction = default_useFunction - !! True if the boundary condition is analytical LOGICAL(LGT) :: isNormal = default_isNormal !! True if the boundary condition is normal to the boundary LOGICAL(LGT) :: isTangent = default_isTangent @@ -81,15 +78,6 @@ MODULE AbstractBC_Class REAL(DFP), ALLOCATABLE :: nodalValue(:, :) !! nodal values are kept here, !! nodalValues( :, its ) denotes nodal values at time step its - PROCEDURE(iface_SpaceTimeFunction), POINTER, NOPASS :: & - & spaceTimeFunction => NULL() - !! SpaceTime Functions - PROCEDURE(iface_SpaceFunction), POINTER, NOPASS :: & - & spaceFunction => NULL() - !! Space Function - PROCEDURE(iface_TimeFunction), POINTER, NOPASS :: & - & timeFunction => NULL() - !! Time function CLASS(UserFunction_), POINTER :: func => NULL() !! User function TYPE(MeshSelection_) :: boundary @@ -141,8 +129,6 @@ MODULE AbstractBC_Class !! Get value of boundary condition in FEVariable_ GENERIC, PUBLIC :: Get => Get1, Get2 !! Generic method to get the boundary condition - PROCEDURE, PUBLIC, PASS(obj) :: GetFromFunction => bc_GetFromFunction - !! Get value from function PROCEDURE, PUBLIC, PASS(obj) :: GetFromUserFunction => & & bc_GetFromUserFunction !! Get value from userfunction @@ -189,7 +175,7 @@ END SUBROUTINE bc_CheckEssentialParam INTERFACE MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & - & name, idof, nodalValueType, useFunction, isNormal, isTangent, & + & name, idof, nodalValueType, isNormal, isTangent, & & useExternal, isUserFunction) TYPE(ParameterList_), INTENT(INOUT) :: param CHARACTER(*), INTENT(IN) :: prefix @@ -202,8 +188,6 @@ MODULE SUBROUTINE SetAbstractBCParam(param, prefix, & INTEGER(I4B), OPTIONAL, INTENT(IN) :: nodalValueType !! Space, Time, SpaceTime, Constant !! default is -1 - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: useFunction - !! use fucntion; default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isUserFunction !! set true when userfucntion is used; default is false LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isNormal @@ -409,23 +393,6 @@ END SUBROUTINE bc_GetFEVar ! date: 2023-11-26 ! summary: Get value from function -INTERFACE - MODULE SUBROUTINE bc_GetFromFunction(obj, nodeNum, nodalValue, times) - CLASS(AbstractBC_), INTENT(IN) :: obj - INTEGER(I4B), INTENT(IN) :: nodeNum(:) - REAL(DFP), ALLOCATABLE, INTENT(INOUT) :: nodalValue(:, :) - REAL(DFP), OPTIONAL, INTENT(IN) :: times(:) - END SUBROUTINE bc_GetFromFunction -END INTERFACE - -!---------------------------------------------------------------------------- -! GetFromFunction@GetMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-26 -! summary: Get value from function - INTERFACE MODULE SUBROUTINE bc_GetFromUserFunction(obj, nodeNum, nodalValue, times) CLASS(AbstractBC_), INTENT(IN) :: obj @@ -462,7 +429,7 @@ END FUNCTION bc_GetDOFNo MODULE PURE SUBROUTINE bc_GetQuery(obj, isInitiated, & & isSelectionByBox, isSelectionByMeshID, isSelectionByElemNum, & & isSelectionByNodeNum, idof, isTangent, isNormal, useFunction, & - & nodalValueType, useExternal) + & nodalValueType, useExternal, isUserFunction) CLASS(AbstractBC_), INTENT(IN) :: obj LOGICAL(LGT), OPTIONAL, INTENT(OUT) :: isInitiated LOGICAL(LGT), OPTIONAL, INTENT(OUT) :: isSelectionByBox @@ -475,6 +442,7 @@ MODULE PURE SUBROUTINE bc_GetQuery(obj, isInitiated, & INTEGER(I4B), OPTIONAL, INTENT(OUT) :: idof INTEGER(I4B), OPTIONAL, INTENT(OUT) :: nodalValueType LOGICAL(LGT), OPTIONAL, INTENT(OUT) :: useExternal + LOGICAL(LGT), OPTIONAL, INTENT(OUT) :: isUserFunction END SUBROUTINE bc_GetQuery END INTERFACE @@ -518,19 +486,12 @@ END FUNCTION bc_IsUseFunction INTERFACE MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & - & timeNodalValue, spaceTimeNodalValue, spaceFunction, timeFunction, & - & spaceTimeFunction, userFunction) + & timeNodalValue, spaceTimeNodalValue, userFunction) CLASS(AbstractBC_), INTENT(INOUT) :: obj REAL(DFP), OPTIONAL, INTENT(IN) :: constantNodalValue REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) - PROCEDURE(iface_SpaceTimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & spaceTimeFunction - PROCEDURE(iface_SpaceFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & spaceFunction - PROCEDURE(iface_TimeFunction), POINTER, OPTIONAL, INTENT(IN) :: & - & timeFunction TYPE(UserFunction_), POINTER, OPTIONAL, INTENT(IN) :: userFunction END SUBROUTINE bc_Set END INTERFACE diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 index 5a9935f07..0c914c9fc 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@ConstructorMethods.F90 @@ -30,7 +30,6 @@ obj%name = '' obj%idof = 0 obj%nodalValueType = -1 -obj%useFunction = .FALSE. obj%isUserFunction = .FALSE. obj%isNormal = .FALSE. obj%isTangent = .FALSE. @@ -44,9 +43,6 @@ END IF obj%func => NULL() -IF (ASSOCIATED(obj%SpaceTimeFunction)) obj%SpaceTimeFunction => NULL() -IF (ASSOCIATED(obj%SpaceFunction)) obj%SpaceFunction => NULL() -IF (ASSOCIATED(obj%TimeFunction)) obj%TimeFunction => NULL() END PROCEDURE bc_Deallocate !---------------------------------------------------------------------------- @@ -65,7 +61,7 @@ prefix0 = obj%GetPrefix() END IF -astr = "/name/idof/nodalValueType/useFunction/isNormal/isTangent/"// & +astr = "/name/idof/nodalValueType/isNormal/isTangent/"// & & "useExternal/isUserFunction" CALL astr%Split(essentialParam, sep="/") @@ -102,9 +98,6 @@ CALL Set(param, datatype=0_I4B, prefix=prefix, key="nodalValueType", & & VALUE=input(option=nodalValueType, default=default_nodalValueType)) -CALL Set(param, datatype=.TRUE., prefix=prefix, key="useFunction", & - & VALUE=input(option=useFunction, default=default_useFunction)) - CALL Set(param, datatype=.TRUE., prefix=prefix, key="isNormal", & & VALUE=input(option=isNormal, default=default_isNormal)) @@ -114,8 +107,13 @@ CALL Set(param, datatype=.TRUE., prefix=prefix, key="useExternal", & & VALUE=input(option=useExternal, default=default_useExternal)) -CALL Set(param, datatype=.TRUE., prefix=prefix, key="isUserFunction", & - & VALUE=input(option=isUserFunction, default=default_useFunction)) +IF (PRESENT(isUserFunction)) THEN + CALL Set(param, datatype=.TRUE., prefix=prefix, key="isUserFunction", & + & VALUE=isUserFunction) +ELSE + CALL Set(param, datatype=.TRUE., prefix=prefix, key="isUserFunction", & + & VALUE=default_isUserFunction) +END IF IF (PRESENT(isNormal) .AND. PRESENT(idof)) THEN IF (idof .GT. 0 .AND. isNormal) THEN @@ -168,10 +166,6 @@ CALL GetValue(obj=param, prefix=prefix%chars(), key="nodalValueType", & & VALUE=obj%nodalValueType) -! useFunction -CALL GetValue(obj=param, prefix=prefix%chars(), key="useFunction", & - & VALUE=obj%useFunction) - ! isUserFunction CALL GetValue(obj=param, prefix=prefix%chars(), key="isUserFunction", & & VALUE=obj%isUserFunction) @@ -191,14 +185,14 @@ ! Check CALL boundary%GetParam(isSelectionByMeshID=isSelectionByMeshID) abool = boundary%isSelectionByMeshID & - & .AND. (.NOT. obj%useFunction) & + & .AND. (.NOT. obj%isUserFunction) & & .AND. (.NOT. obj%useExternal) & & .AND. (obj%nodalValueType .NE. Constant) IF (abool) THEN CALL e%RaiseWarning(modName//'::'//myName//" - "// & & "When meshSelection is by MeshID"//CHAR_LF// & - & " and `useFunction` is false, then"//CHAR_LF// & + & " and `isUserFunction` is false, then"//CHAR_LF// & & " `nodalValueType` in `AbstractBC_`"//CHAR_LF// & & " object should be Constant.") END IF diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 index d0655c229..ebe68b95d 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@GetMethods.F90 @@ -71,12 +71,6 @@ isNodalValuePresent = PRESENT(nodalValue) -IF (isNodalValuePresent .AND. obj%useFunction) THEN - CALL obj%GetFromFunction(nodeNum=nodeNum, nodalValue=nodalValue, & - & times=times) - RETURN -END IF - IF (isNodalValuePresent .AND. obj%isUserFunction) THEN CALL obj%GetFromUserFunction(nodeNum=nodeNum, nodalValue=nodalValue, & & times=times) @@ -173,102 +167,8 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE bc_GetFromFunction -CHARACTER(*), PARAMETER :: myName = "bc_GetFromFunction" -INTEGER(I4B) :: ii, kk -REAL(DFP), POINTER :: xij(:, :) - -! get pointer to nodecoord - -xij => obj%dom%getNodeCoordPointer() - -SELECT CASE (obj%nodalValueType) - -! Space -CASE (Space) - - IF (.NOT. ASSOCIATED(obj%SpaceFunction)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "When nodalValueType is & - & Space and useFunction is specified, & - & then SpaceFunction is needed, & - & but it is not associated") - END IF - - CALL Reallocate(nodalValue, SIZE(nodeNum), 1) - - DO ii = 1, SIZE(nodeNum) - nodalValue(ii, 1) = obj%SpaceFunction( & - & x=xij(:, obj%dom%getLocalNodeNumber(globalNode=nodeNum(ii)))) - END DO - -! Time -CASE (Time) - - IF (.NOT. ASSOCIATED(obj%TimeFunction)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "When nodalValueType is Time & - & and useFunction is specified, & - & then TimeFunction is needed, & - & but it is not associated") - END IF - - IF (.NOT. PRESENT(times)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "When `nodalValueType` is Time & - & and `useFunction` is TRUE, & - & then `times` is needed in the passing argument, & - & but it is not present") - END IF - - CALL Reallocate(nodalValue, SIZE(nodeNum), SIZE(times)) - - DO ii = 1, SIZE(times) - nodalValue(:, ii) = obj%TimeFunction(t=times(ii)) - END DO - -! SpaceTime -CASE (SpaceTime) - - IF (.NOT. ASSOCIATED(obj%SpaceTimeFunction)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "When `nodalValueType` is `SpaceTime` and & - & `useFunction` is specified, & - & then `SpaceTimeFunction` is needed, & - & but it is not associated") - END IF - - IF (.NOT. PRESENT(times)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "When `nodalValueType` is `SpaceTime` & - & and `useFunction` is True, & - & then `times` is needed as argument, & - & but it is not present") - END IF - - CALL Reallocate(nodalValue, SIZE(nodeNum), SIZE(times)) - - DO kk = 1, SIZE(times) - DO ii = 1, SIZE(nodeNum) - nodalValue(ii, kk) = & - & obj%SpaceTimeFunction( & - & x=xij(:, obj%dom%getLocalNodeNumber(globalNode=nodeNum(ii))), & - & t=times(kk)) - END DO - END DO - -END SELECT - -NULLIFY (xij) - -END PROCEDURE bc_GetFromFunction - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - MODULE PROCEDURE bc_isuseFunction -ans = obj%useFunction +ans = obj%isUserFunction END PROCEDURE bc_isuseFunction !---------------------------------------------------------------------------- @@ -285,7 +185,8 @@ IF (PRESENT(idof)) idof = obj%idof IF (PRESENT(isTangent)) isTangent = obj%isTangent IF (PRESENT(isNormal)) isNormal = obj%isNormal -IF (PRESENT(useFunction)) useFunction = obj%useFunction +IF (PRESENT(useFunction)) useFunction = obj%isUserFunction +IF (PRESENT(isUserFunction)) isUserFunction = obj%isUserFunction IF (PRESENT(nodalValueType)) nodalValueType = obj%nodalValueType IF (PRESENT(isInitiated)) isInitiated = obj%isInitiated IF (PRESENT(useExternal)) useExternal = obj%useExternal @@ -363,7 +264,7 @@ CALL obj%dom%GetNodeCoord(nodeCoord=xij(1:nsd, 1:1), & & globalNode=nodeNum(1:1)) - CALL obj%func%Get(val=ans, args=xij(1:nsd, 1)) + CALL obj%func%Get(val=ans) nodalValue(:, 1) = ans @@ -375,7 +276,7 @@ CALL obj%dom%GetNodeCoord(nodeCoord=xij(1:nsd, 1:1), & & globalNode=nodeNum(ii:ii)) - CALL obj%func%Get(val=ans, args=xij(1:nsd, 1)) + CALL obj%func%Get(val=ans, args=xij(1:3, 1)) nodalValue(ii, 1) = ans END DO @@ -406,7 +307,7 @@ CALL obj%dom%GetNodeCoord(nodeCoord=xij(1:nsd, 1:1), & & globalNode=nodeNum(ii:ii)) - CALL obj%func%Get(val=ans, args=xij(1:nsd + 1, 1)) + CALL obj%func%Get(val=ans, args=xij(1:4, 1)) nodalValue(ii, kk) = ans END DO diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 index 8e19a1348..1c4cc3104 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@IOMethods.F90 @@ -108,16 +108,8 @@ IF (obj%isUserFunction) THEN ALLOCATE (obj%func) - CALL obj%func%IMPORT(hdf5=hdf5, & - & group=TRIM(group)//"/userFunction") -END IF - -dsetname = TRIM(group)//"/useFunction" -IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & 'The dataset useFunction should be present') -ELSE - CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%useFunction) + dsetname = TRIM(group)//"/userFunction" + CALL obj%func%IMPORT(hdf5=hdf5, group=dsetname%chars()) END IF dsetname = TRIM(group)//"/useExternal" @@ -136,7 +128,7 @@ CALL obj%boundary%IMPORT(hdf5=hdf5, group=dsetname%chars()) END IF -IF (.NOT. obj%useFunction) THEN +IF (.NOT. obj%isUserFunction) THEN dsetname = TRIM(group)//"/nodalValue" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & @@ -221,9 +213,14 @@ END SELECT CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) -! WRITE useFunction -dsetname = TRIM(group)//"/useFunction" -CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%useFunction) +! WRITE isUserFunction +dsetname = TRIM(group)//"/isUserFunction" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isUserFunction) + +IF (ASSOCIATED(obj%func)) THEN + dsetname = TRIM(group)//"/userFunction" + CALL obj%func%Export(hdf5=hdf5, group=dsetname%chars()) +END IF ! WRITE useExternal dsetname = TRIM(group)//"/useExternal" @@ -234,7 +231,7 @@ CALL obj%boundary%export(hdf5=hdf5, group=dsetname%chars()) ! Read nodalValue -IF (.NOT. obj%UseFunction) THEN +IF (.NOT. obj%isUserFunction) THEN dsetname = TRIM(group)//"/nodalValue" IF (.NOT. ALLOCATED(obj%nodalValue)) THEN @@ -294,11 +291,10 @@ CALL Display("nodalValueType : "//TRIM(strval%chars()), unitNo=unitNo) CALL Display(obj%isUserFunction, "isUserFunction : ", unitNo=unitNo) -CALL Display(obj%useFunction, "useFunction : ", unitNo=unitNo) CALL Display(obj%useExternal, "useExternal : ", unitNo=unitNo) CALL obj%Boundary%Display(msg="Boundary : ", unitNo=unitNo) -IF (.NOT. obj%UseFunction) THEN +IF (.NOT. obj%isUserFunction) THEN IF (.NOT. ALLOCATED(obj%nodalValue)) THEN CALL Display("nodalValue : NOT ALLOCATED", unitNo=unitNo) ELSE @@ -336,8 +332,7 @@ MODULE PROCEDURE bc_ImportParamFromToml CHARACTER(*), PARAMETER :: myName = "bc_ImportParamFromToml()" INTEGER(I4B) :: origin, stat, nodalValueType, idof -LOGICAL(LGT) :: useFunction, isNormal, isTangent, useExternal, & -& isUserFunction +LOGICAL(LGT) :: isNormal, isTangent, isUserFunction, useExternal TYPE(String) :: nodalValueType_string, name, astr #ifdef DEBUG_VER @@ -345,11 +340,8 @@ & '[START] ImportParamFromToml()') #endif -CALL toml_get(table, "useFunction", useFunction, & - & default_useFunction, origin=origin, stat=stat) - CALL toml_get(table, "isUserFunction", isUserFunction, & - & default_useFunction, origin=origin, stat=stat) + & default_isUserFunction, origin=origin, stat=stat) CALL toml_get(table, "isTangent", isTangent, & & default_isTangent, origin=origin, stat=stat) @@ -389,7 +381,6 @@ & name=name%chars(), & & idof=idof, & & nodalValueType=nodalValueType, & - & useFunction=useFunction, & & isUserFunction=isUserFunction, & & isNormal=isNormal, & & isTangent=isTangent, & @@ -454,22 +445,18 @@ ALLOCATE (obj%func) CALL obj%func%ImportFromToml(table=node) -END IF - -IF (obj%useFunction) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: useFunction = .TRUE., currently you cannot '// & - & 'specify the function.') RETURN END IF SELECT CASE (obj%nodalValueType) CASE (Constant) CALL toml_get(table, "value", constantValue, origin=origin, stat=stat) - IF (stat .NE. toml_stat%success) THEN + bool1 = stat .NE. toml_stat%success + IF (bool1) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: nodalValueType is Constant. So, '// & - & 'value should be a constant (scalar real value).') + & '[CONFIG ERROR] :: nodalValueType is Constant. '// & + & 'obj%isUserFunction is False. So, '// & + & 'value should be a present (scalar real value).') RETURN END IF CALL obj%Set(constantnodalValue=constantValue) @@ -482,7 +469,8 @@ IF (bool1) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & + & '[CONFIG ERROR] :: nodalValueType is Space or Time.'// & + & 'obj%isUserFunction is False. So, '// & & 'value should be a vector of real numbers.'//CHAR_LF// & & 'You can specify a vector by directly giving the vector values.'// & & 'Otherwise, specify filename which contains the vector'// & @@ -504,7 +492,8 @@ IF (bool1) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[CONFIG ERROR] :: nodalValueType is Space or Time. So '// & + & '[CONFIG ERROR] :: nodalValueType is Space or Time.'// & + & 'obj%isUserFunction is False. So, '// & & 'value should be a vector of real numbers.'//CHAR_LF// & & 'You can specify a vector by directly giving the vector values.'// & & 'Otherwise, specify filename which contains the vector'// & diff --git a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 index 83baba28b..377c3ed09 100644 --- a/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 +++ b/src/submodules/AbstractBC/src/AbstractBC_Class@SetMethods.F90 @@ -26,8 +26,8 @@ MODULE PROCEDURE bc_Set CHARACTER(*), PARAMETER :: myName = "bc_Set" -LOGICAL(LGT) :: notFunc_notExt, isTimeFunc, isSpaceFunc, isSTFunc, isFunc, & - & isConstVal, isSpaceVal, isSTVal, isTimeVal, bool1, bool2, isUserFunction +LOGICAL(LGT) :: notFunc_notExt, isConstVal, isSpaceVal, isSTVal, & + & isTimeVal, bool1, bool2, isUserFunction #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & @@ -39,24 +39,19 @@ & '[CONFIG ERROR ] :: AbstractBC_ object is not initiated.') END IF -notFunc_notExt = (.NOT. obj%useFunction) .AND. & -& (.NOT. obj%useExternal) +notFunc_notExt = (.NOT. obj%isUserFunction) .AND. (.NOT. obj%useExternal) isUserFunction = PRESENT(userFunction) -isTimeFunc = PRESENT(timeFunction) -isSpaceFunc = PRESENT(spaceFunction) -isSTFunc = PRESENT(spaceTimeFunction) -isFunc = isSpaceFunc .OR. isTimeFunc .OR. isSTFunc isConstVal = PRESENT(constantNodalValue) isSpaceVal = PRESENT(spaceNodalValue) isTimeVal = PRESENT(timeNodalValue) isSTVal = PRESENT(spaceTimeNodalValue) -IF (notFunc_notExt .AND. isFunc) THEN +IF (notFunc_notExt .AND. isUserFunction) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "//CHAR_LF// & & "with useFunction=.FALSE. and useExternal=.FALSE."//CHAR_LF// & - & "So you cannot provide timeFunction, spaceFunction, spaceTimeFunction") + & "So you cannot provide userFunction.") END IF bool1 = notFunc_notExt .AND. isConstVal @@ -65,7 +60,7 @@ CALL e%RaiseError(modName//'::'//myName//" - "// & & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & & "with nodalValueType=Constant "//CHAR_LF// & - & 'So, constantNodalValue cannot be present') + & 'So, constantNodalValue cannot be present.') RETURN END IF @@ -140,63 +135,6 @@ RETURN END IF -! spaceFunction -bool1 = isSpaceFunc .AND. (obj%nodalValueType .NE. Space) -IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated "// & - & "with nodalValueType=Space"// & - & CHAR_LF//'So, spaceFunction cannot be present') - RETURN -END IF - -IF (isSpaceFunc) THEN - obj%spaceFunction => spaceFunction - RETURN -END IF - -! timeFunction -bool1 = isTimeFunc .AND. (obj%nodalValueType .NE. Time) -IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & - & "nodalValueType=Time"// & - & CHAR_LF// & - & 'So, timeFunction cannot be present') - RETURN -END IF - -IF (isTimeFunc) THEN - obj%timeFunction => timeFunction - RETURN -END IF - -! spaceTimeFunction -bool1 = isSTFunc .AND. (obj%nodalValueType .NE. SpaceTime) -IF (bool1) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is not initiated with "// & - & "nodalValueType=SpaceTime"// & - & CHAR_LF// & - & 'So, spaceTimeFunction cannot be present') - RETURN -END IF - -IF (isSTFunc) THEN - obj%spaceTimeFunction => spaceTimeFunction - RETURN -END IF - -IF (obj%useFunction .AND. (.NOT. isFunc)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & "[CONFIG ERROR] :: AbstractBC_::obj is initiated "// & - & "with useFunction=TRUE"// & - & CHAR_LF// & - & 'So, spaceFunction, timeFunction, or spaceTimeFunction '// & - & 'should be present') - RETURN -END IF - #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & & '[END] Set()') From b899ac2e9de79a65f6cd69a7c07548e9d2e19129 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:35:26 +0900 Subject: [PATCH 069/117] Adding AbstractMaterial --- src/modules/AbstractMaterial/CMakeLists.txt | 22 ++ .../src/AbstractMaterial.toml | 34 ++ .../src/AbstractMaterial_Class.F90 | 354 ++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 src/modules/AbstractMaterial/CMakeLists.txt create mode 100644 src/modules/AbstractMaterial/src/AbstractMaterial.toml create mode 100644 src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 diff --git a/src/modules/AbstractMaterial/CMakeLists.txt b/src/modules/AbstractMaterial/CMakeLists.txt new file mode 100644 index 000000000..7d94b8f86 --- /dev/null +++ b/src/modules/AbstractMaterial/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractMaterial_Class.F90 +) \ No newline at end of file diff --git a/src/modules/AbstractMaterial/src/AbstractMaterial.toml b/src/modules/AbstractMaterial/src/AbstractMaterial.toml new file mode 100644 index 000000000..501ca3841 --- /dev/null +++ b/src/modules/AbstractMaterial/src/AbstractMaterial.toml @@ -0,0 +1,34 @@ +[[material]] +returnType = "Scalar" +# returnType = "Vector" +# returnType = "Matrix" +argType = "Space" +# argType = "Constant" +# argType = "Space" +# argType = "Time" +# argType = "SpaceTime" +numArgs = 3 +numReturns = 1 +luaScript = "./hello.lua" +luaFunctionName="hello" +scalarValue = 1.0 +vectorValue = [1.0, 2.0, 3.0] +matrixValue = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]] + +[[material]] +returnType = "Scalar" +# returnType = "Vector" +# returnType = "Matrix" +argType = "Space" +# argType = "Constant" +# argType = "Space" +# argType = "Time" +# argType = "SpaceTime" +numArgs = 3 +numReturns = 1 +luaScript = "./hello.lua" +luaFunctionName="hello" +scalarValue = 1.0 +vectorValue = [1.0, 2.0, 3.0] +matrixValue = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]] + diff --git a/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 b/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 new file mode 100644 index 000000000..2238e45c9 --- /dev/null +++ b/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 @@ -0,0 +1,354 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Abstract class for Material behavior + +MODULE AbstractMaterial_Class +USE GlobalData +USE String_Class +USE BaseType +USE UserFunction_Class +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE TxtFile_Class +USE tomlf, ONLY: toml_table +USE Fhash, ONLY: FhashTable_ => fhash_tbl_t +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "AbstractMaterial_Class" +CHARACTER(*), PARAMETER :: myprefix = "AbstractMaterial" +REAL(DFP), PARAMETER :: expandScale1 = 2 +REAL(DFP), PARAMETER :: expandScale2 = 1.2 +INTEGER(I4B), PARAMETER :: thresholdSize = 20 + +PUBLIC :: AbstractMaterial_ +PUBLIC :: AbstractMaterialPointer_ +PUBLIC :: SetAbstractMaterialParam +PUBLIC :: AbstractMaterialInitiate +PUBLIC :: AbstractMaterialDeallocate +PUBLIC :: AbstractMaterialImport +PUBLIC :: AbstractMaterialExport +PUBLIC :: AbstractMaterialDisplay +PUBLIC :: AbstractMaterialImportFromToml + +!---------------------------------------------------------------------------- +! AbstractMaterial_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 1 Oct 2021 +! summary: Abstract Material class +! +!# Introduction +! +! Abstract class for defining material and material behavior +! +!@todo +! Add following routines +! - setMaterialParam( prefix, param, ... ) +! - Import( hdf5, group ), import if present +! are not present in hdf5, then report error +! - Export( hdf5, group ), export all +! - setMaterialParameters(obj, param) +! - getMaterialParameters(obj, param) +!@endtodo +! +!@todo +! Currently there is a lot of code repreatation while implementing the +! [[AbstractMaterial_]] class. Try to minimize it by putting routines +! in [[AbstractMaterial_Class]] module. +!@endtodo + +TYPE, ABSTRACT :: AbstractMaterial_ + PRIVATE + LOGICAL(LGT) :: isInit = .FALSE. + INTEGER(I4B) :: tProperties = 0_I4B + !! Total number of properties + TYPE(String) :: name + !! name of the material + TYPE(FhashTable_) :: tbl + !! Hash table for name to index mapping + TYPE(UserFunctionPointer_), ALLOCATABLE :: matProps(:) + !! material properties +CONTAINS + PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & am_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => am_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => am_Deallocate + + ! IO: + ! @IOMethods + PROCEDURE, PUBLIC, PASS(obj) :: Display => am_Display + PROCEDURE, PUBLIC, PASS(obj) :: Export => am_Export + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => am_Import + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml1 => & + & am_ImportFromToml1 + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml2 => & + & am_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromTom => ImportFromToml1, & + & ImportFromToml2 + + ! GET: + ! @GetMethods + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => am_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: GetMaterialPointer => & + & am_GetMaterialPointer + PROCEDURE, PUBLIC, PASS(obj) :: IsMaterialPresent => am_IsMaterialPresent + + ! SET: + ! @SetMethods + PROCEDURE, PASS(obj) :: AddMaterial1 => am_AddMaterial1 + PROCEDURE, PASS(obj) :: AddMaterial2 => am_AddMaterial2 + GENERIC, PUBLIC :: AddMaterial => AddMaterial1, AddMaterial2 + PROCEDURE, PUBLIC, PASS(obj) :: ExpandMatProps => am_ExpandMatProps +END TYPE AbstractMaterial_ + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE :: AbstractMaterialPointer_ + CLASS(AbstractMaterial_), POINTER :: ptr => NULL() +END TYPE AbstractMaterialPointer_ + +!---------------------------------------------------------------------------- +! SetAbstractMaterialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2021-12-08 +! update: 2021-12-08 +! summary: Sets parameter for abstract material + +INTERFACE + MODULE SUBROUTINE SetAbstractMaterialParam(param, prefix, name) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: prefix + CHARACTER(*), INTENT(IN) :: name + END SUBROUTINE SetAbstractMaterialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Check essential parameters + +INTERFACE + MODULE SUBROUTINE am_CheckEssentialParam(obj, param) + CLASS(AbstractMaterial_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE am_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 26 Oct 2021 +! summary: Initiate the material + +INTERFACE AbstractMaterialInitiate + MODULE SUBROUTINE am_Initiate(obj, param, prefix) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE am_Initiate +END INTERFACE AbstractMaterialInitiate + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 26 Oct 2021 +! summary: Deallocate data + +INTERFACE AbstractMaterialDeallocate + MODULE SUBROUTINE am_Deallocate(obj) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE am_Deallocate +END INTERFACE AbstractMaterialDeallocate + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-18 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION am_GetPrefix(obj) RESULT(ans) + CLASS(AbstractMaterial_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION am_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! AddMaterial@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Add material + +INTERFACE + MODULE SUBROUTINE am_AddMaterial1(obj, name) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: name + END SUBROUTINE am_AddMaterial1 +END INTERFACE + +!---------------------------------------------------------------------------- +! AddMaterial@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Add material + +INTERFACE + MODULE SUBROUTINE am_AddMaterial2(obj, name) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name(:) + END SUBROUTINE am_AddMaterial2 +END INTERFACE + +!---------------------------------------------------------------------------- +! ExpandMatProps@SetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE am_ExpandMatProps(obj) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE am_ExpandMatProps +END INTERFACE + +!---------------------------------------------------------------------------- +! IsMaterialPresent@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Add material + +INTERFACE + MODULE FUNCTION am_IsMaterialPresent(obj, name) RESULT(ans) + CLASS(AbstractMaterial_), INTENT(IN) :: obj + CHARACTER(*), INTENT(IN) :: name + LOGICAL(LGT) :: ans + END FUNCTION am_IsMaterialPresent +END INTERFACE + +!---------------------------------------------------------------------------- +! GetMaterial@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Get material + +INTERFACE + MODULE FUNCTION am_GetMaterialPointer(obj, name) RESULT(matPtr) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: name + TYPE(UserFunction_), POINTER :: matPtr + END FUNCTION am_GetMaterialPointer +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +INTERFACE AbstractMaterialImport + MODULE SUBROUTINE am_Import(obj, hdf5, group) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE am_Import +END INTERFACE AbstractMaterialImport + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +INTERFACE AbstractMaterialExport + MODULE SUBROUTINE am_Export(obj, hdf5, group) + CLASS(AbstractMaterial_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE am_Export +END INTERFACE AbstractMaterialExport + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +INTERFACE AbstractMaterialDisplay + MODULE SUBROUTINE am_Display(obj, msg, unitNo) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE am_Display +END INTERFACE AbstractMaterialDisplay + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE AbstractMaterialImportFromToml + MODULE SUBROUTINE am_ImportFromToml1(obj, table) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE am_ImportFromToml1 +END INTERFACE AbstractMaterialImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE AbstractMaterialImportFromToml + MODULE SUBROUTINE am_ImportFromToml2(obj, tomlName, afile, filename, & + & printToml) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE am_ImportFromToml2 +END INTERFACE AbstractMaterialImportFromToml + +END MODULE AbstractMaterial_Class From 612d7a6e33d841e715033862ab35b222d8934686 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:36:01 +0900 Subject: [PATCH 070/117] Adding SolidMaterial --- src/modules/SolidMaterial/CMakeLists.txt | 22 ++ .../SolidMaterial/src/SolidMaterial_Class.F90 | 352 ++++++++++++++++++ 2 files changed, 374 insertions(+) create mode 100644 src/modules/SolidMaterial/CMakeLists.txt create mode 100644 src/modules/SolidMaterial/src/SolidMaterial_Class.F90 diff --git a/src/modules/SolidMaterial/CMakeLists.txt b/src/modules/SolidMaterial/CMakeLists.txt new file mode 100644 index 000000000..e96f580ab --- /dev/null +++ b/src/modules/SolidMaterial/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/SolidMaterial_Class.F90 +) \ No newline at end of file diff --git a/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 b/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 new file mode 100644 index 000000000..bdf7df8fd --- /dev/null +++ b/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 @@ -0,0 +1,352 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This module defines a class called [[SolidMaterial_]] +! +!# Introduction +! +! This module defines a class called [[SolidMaterial_]], which defines a +! solid material and its behavior. Other than defining the class, +! this module makes a routine called +! [[SolidMaterial_Class:SetSolidMaterialParam]] public. +! This routine can be used for setting the options in [[ParameterList_]] +! object. + +MODULE SolidMaterial_Class +USE GlobalData +USE String_Class +USE BaseType +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractMaterial_Class +USE AbstractSolidMechanicsModel_Class +USE MeshSelection_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "SolidMaterial_Class" +CHARACTER(*), PARAMETER :: myprefix = "SolidMaterial" +PUBLIC :: SolidMaterial_ +PUBLIC :: SolidMaterialPointer_ +PUBLIC :: DEALLOCATE +PUBLIC :: SetSolidMaterialParam +PUBLIC :: AddSolidMaterial +PUBLIC :: TypeSolidMaterial + +!---------------------------------------------------------------------------- +! SolidMaterial_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 1 Oct 2021 +! summary: SolidMaterial class for material modeling of solids +! +!# Introduction +! SolidMaterial class is a child of [[AbstractMaterial_]]. +! It is used for modeling the behavior of solids. + +TYPE, EXTENDS(AbstractMaterial_) :: SolidMaterial_ + CLASS(AbstractSolidMechanicsModel_), POINTER :: stressStrainModel => NULL() + !! Pointer to stress strain material behavior of solids +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & solid_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => solid_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => solid_Deallocate + FINAL :: solid_Final + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => solid_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => solid_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => solid_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetStressStrainModelPointer => & + & solid_GetStressStrainModelPointer + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => solid_GetPrefix +END TYPE SolidMaterial_ + +TYPE(SolidMaterial_), PARAMETER :: TypeSolidMaterial = SolidMaterial_() + +!---------------------------------------------------------------------------- +! SolidMaterialPointer_ +!---------------------------------------------------------------------------- + +TYPE :: SolidMaterialPointer_ + CLASS(SolidMaterial_), POINTER :: ptr => NULL() +END TYPE SolidMaterialPointer_ + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Deallocate the vector + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Vector(obj) + TYPE(SolidMaterial_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Vector +END INTERFACE DEALLOCATE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Deallocate the vector of pointer + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Ptr_Vector(obj) + TYPE(SolidMaterialPointer_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Ptr_Vector +END INTERFACE DEALLOCATE + +!---------------------------------------------------------------------------- +! SetSolidMaterialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine sets the essential parameter for [[SolidMaterial_]] +! +!# Introduction +! +! This routine sets the essential parameter for [[SolidMaterial_]]. +! It sets values for +! +! - `SolidMaterial/name` +! - `SolidMaterial/massDensity` +! - `SolidMaterial/stresStrainModel` + +INTERFACE + MODULE SUBROUTINE SetSolidMaterialParam(param, name, stressStrainModel) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: name + !! It is the name of the material + CHARACTER(*), OPTIONAL, INTENT(IN) :: stressStrainModel + !! Name of the child-class of `AbstractSolidMechanicsModel_` + !! For example `LinearElasticModel` + END SUBROUTINE SetSolidMaterialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine Checks the essential parameter for [[SolidMaterial_]] +! +!# Introduction +! +! This routine Checks the essential parameter for [[SolidMaterial_]]. +! It Checks the existance of +! +! - `SolidMaterial/name` +! - `SolidMaterial/massDensity` +! - `SolidMaterial/stresStrainModel` + +INTERFACE + MODULE SUBROUTINE solid_CheckEssentialParam(obj, param) + CLASS(SolidMaterial_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE solid_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the instance of `SolidMaterial` +! +!# Introduction +! This routine initiates the instance of `SolidMaterial_`. +! It reads the options from `param`, and sets the options of `SolidMaterial` +! +!- `SolidMaterial/name` +!- `SolidMaterial/massDensity` +!- `SolidMaterial/stresStrainModel` +! +! This routine calls the [[MaterialFactory:SolidMechanicsModelFactory]] to +! construct the [[SolidMaterial_:stressStrainModel]]. +! +!@warning +! If the `SolidMaterial/stressStrainModel` is already associated, then +! the routine will produce error, so make sure the +! [[SolidMaterial_:stressStrainModel]] is nullified before calling it. +!@endwarning + +INTERFACE + MODULE SUBROUTINE solid_Initiate(obj, param, prefix) + CLASS(SolidMaterial_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE solid_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine deallocates the instance +! +!# Introduction +! +! This routine deallocates the memory allocated to the instance of +! `SolidMaterial_`. +! +!@warning +! This routine also deallocates [[SolidMaterial_:stressStrainModel]], if +! it is associated. +!@endwarning + +INTERFACE + MODULE SUBROUTINE solid_Deallocate(obj) + CLASS(SolidMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE solid_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine deallocates the instance + +INTERFACE + MODULE SUBROUTINE solid_Final(obj) + TYPE(SolidMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE solid_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the instance from hdf5 file +! +!# Introduction +! This routine also deallocates the data associated +! summary: This routine initiates the instance from hdf5 file +! + +INTERFACE + MODULE SUBROUTINE solid_Import(obj, hdf5, group) + CLASS(SolidMaterial_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE solid_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine exports the information to external hdf5 file + +INTERFACE + MODULE SUBROUTINE solid_Export(obj, hdf5, group) + CLASS(SolidMaterial_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE solid_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine displays the content of the instance + +INTERFACE + MODULE SUBROUTINE solid_Display(obj, msg, unitNo) + CLASS(SolidMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE solid_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetStressStrainModelPointer@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-02-10 +! summary: Get stressStrainModel pointer + +INTERFACE + MODULE FUNCTION solid_GetStressStrainModelPointer(obj) RESULT(ans) + CLASS(SolidMaterial_), INTENT(IN) :: obj + CLASS(AbstractSolidMechanicsModel_), POINTER :: ans + END FUNCTION solid_GetStressStrainModelPointer +END INTERFACE + +!---------------------------------------------------------------------------- +! AddSolidMaterial@SetMethod +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-11 +! summary: Add a solid material to the vector of SolidMaterialPointer_ + +INTERFACE AddSolidMaterial + MODULE SUBROUTINE solid_AddSolidMaterial( & + & obj, & + & tMaterials, & + & materialNo, & + & materialName, & + & solidMaterialToMesh, & + & param, & + & region) + TYPE(SolidMaterialPointer_), INTENT(INOUT) :: obj(:) + INTEGER(I4B), INTENT(IN) :: tMaterials + INTEGER(I4B), INTENT(IN) :: materialNo + CHARACTER(*), OPTIONAL, INTENT(IN) :: materialName + TYPE(ParameterList_), OPTIONAL, INTENT(IN) :: param + TYPE(MeshSelection_), OPTIONAL, INTENT(IN) :: region + TYPE(MeshSelection_), OPTIONAL, INTENT(INOUT) :: solidMaterialToMesh(:) + END SUBROUTINE solid_AddSolidMaterial +END INTERFACE AddSolidMaterial + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION solid_GetPrefix(obj) RESULT(ans) + CLASS(SolidMaterial_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION solid_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE SolidMaterial_Class From 039db4702b2ed02d06364279599cec3c4b1ee232 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:36:13 +0900 Subject: [PATCH 071/117] Adding PorousMaterial --- src/modules/PorousMaterial/CMakeLists.txt | 22 ++ .../src/PorousMaterial_Class.F90 | 257 ++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 src/modules/PorousMaterial/CMakeLists.txt create mode 100644 src/modules/PorousMaterial/src/PorousMaterial_Class.F90 diff --git a/src/modules/PorousMaterial/CMakeLists.txt b/src/modules/PorousMaterial/CMakeLists.txt new file mode 100644 index 000000000..1a36df3fa --- /dev/null +++ b/src/modules/PorousMaterial/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/PorousMaterial_Class.F90 +) \ No newline at end of file diff --git a/src/modules/PorousMaterial/src/PorousMaterial_Class.F90 b/src/modules/PorousMaterial/src/PorousMaterial_Class.F90 new file mode 100644 index 000000000..1bad82697 --- /dev/null +++ b/src/modules/PorousMaterial/src/PorousMaterial_Class.F90 @@ -0,0 +1,257 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This module defines a class called [[PorousMaterial_]] +! +!# Introduction +! +! This module defines a class called [[PorousMaterial_]], which defines a +! Porous material and its behavior. Other than defining the class, +! this module makes a routine called +! [[PorousMaterial_Class:SetPorousMaterialParam]] public. +! This routine can be used for Setting the options in [[ParameterList_]] +! object. + +MODULE PorousMaterial_Class +USE GlobalData +USE String_Class +USE BaSetype +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractMaterial_Class +USE AbstractPoroMechanicsModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "PorousMaterial_Class" +CHARACTER(*), PARAMETER :: myprefix = "PorousMaterial" +PUBLIC :: PorousMaterial_ +PUBLIC :: TypePorousMaterial +PUBLIC :: PorousMaterialPointer_ +PUBLIC :: SetPorousMaterialParam + +!---------------------------------------------------------------------------- +! PorousMaterial_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 1 Oct 2021 +! summary: porousMaterial class for material modeling of Porouss +! +!# Introduction +! porousMaterial class is a child of [[AbstractMaterial_]]. +! It is used for modeling the behavior of Porouss. + +TYPE, EXTENDS(AbstractMaterial_) :: PorousMaterial_ + CLASS(AbstractPoroMechanicsModel_), POINTER :: stressStrainModel => NULL() + !! Pointer to stress strain material behavior of Porouss +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & Porous_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => Porous_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => Porous_Deallocate + FINAL :: Porous_Final + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => Porous_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => Porous_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => Porous_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => Porous_GetPrefix +END TYPE PorousMaterial_ + +TYPE(PorousMaterial_), PARAMETER :: TypePorousMaterial = PorousMaterial_() + +!---------------------------------------------------------------------------- +! PorousMaterialPointer_ +!---------------------------------------------------------------------------- + +TYPE :: PorousMaterialPointer_ + CLASS(PorousMaterial_), POINTER :: ptr => NULL() +END TYPE PorousMaterialPointer_ + +!---------------------------------------------------------------------------- +! SetPorousMaterialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine Sets the essential parameter for [[PorousMaterial_]] +! +!# Introduction +! +! This routine Sets the essential parameter for [[PorousMaterial_]]. +! It Sets values for +! +! - `porousMaterial/name` +! - `porousMaterial/massDensity` +! - `porousMaterial/stresStrainModel` + +INTERFACE + MODULE SUBROUTINE SetPorousMaterialParam(param, name, stressStrainModel) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: name + !! It is the name of the material + CHARACTER(*), OPTIONAL, INTENT(IN) :: stressStrainModel + !! Name of the child-class of `AbstractPorousMechanicsModel_` + !! For example `LinearElasticModel` + END SUBROUTINE SetPorousMaterialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine Checks the essential parameter for [[PorousMaterial_]] +! +!# Introduction +! +! This routine Checks the essential parameter for [[PorousMaterial_]]. +! It Checks the existance of +! +! - `porousMaterial/name` + +INTERFACE + MODULE SUBROUTINE Porous_CheckEssentialParam(obj, param) + CLASS(PorousMaterial_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE Porous_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the instance of `porousMaterial` + +INTERFACE + MODULE SUBROUTINE Porous_Initiate(obj, param, prefix) + CLASS(PorousMaterial_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE Porous_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine deallocates the instance +! +!# Introduction +! +! This routine deallocates the memory allocated to the instance of +! `PorousMaterial_`. +! +!@warning +! This routine also deallocates [[PorousMaterial_:stressStrainModel]], if +! it is associated. +!@endwarning + +INTERFACE + MODULE SUBROUTINE Porous_Deallocate(obj) + CLASS(PorousMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE Porous_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine deallocates the instance + +INTERFACE + MODULE SUBROUTINE Porous_Final(obj) + TYPE(PorousMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE Porous_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the instance from hdf5 file +! +!# Introduction +! This routine also deallocates the data associated +! summary: This routine initiates the instance from hdf5 file + +INTERFACE + MODULE SUBROUTINE Porous_Import(obj, hdf5, group) + CLASS(PorousMaterial_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE Porous_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine exports the information to external hdf5 file + +INTERFACE + MODULE SUBROUTINE Porous_Export(obj, hdf5, group) + CLASS(PorousMaterial_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE Porous_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine displays the content of the instance + +INTERFACE + MODULE SUBROUTINE Porous_Display(obj, msg, unitNo) + CLASS(PorousMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE Porous_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION Porous_GetPrefix(obj) RESULT(ans) + CLASS(PorousMaterial_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION Porous_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE PorousMaterial_Class From f73aacd0e74cff970e09465ebe718226ca1992ef Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:36:38 +0900 Subject: [PATCH 072/117] Adding NewtonianFluidModel --- .../NewtonianFluidModel/CMakeLists.txt | 22 + .../src/NewtonianFluidModel_Class.F90 | 582 ++++++++++++++++++ 2 files changed, 604 insertions(+) create mode 100644 src/modules/NewtonianFluidModel/CMakeLists.txt create mode 100644 src/modules/NewtonianFluidModel/src/NewtonianFluidModel_Class.F90 diff --git a/src/modules/NewtonianFluidModel/CMakeLists.txt b/src/modules/NewtonianFluidModel/CMakeLists.txt new file mode 100644 index 000000000..09f979e63 --- /dev/null +++ b/src/modules/NewtonianFluidModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/NewtonianFluidModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/NewtonianFluidModel/src/NewtonianFluidModel_Class.F90 b/src/modules/NewtonianFluidModel/src/NewtonianFluidModel_Class.F90 new file mode 100644 index 000000000..bb5ddc76b --- /dev/null +++ b/src/modules/NewtonianFluidModel/src/NewtonianFluidModel_Class.F90 @@ -0,0 +1,582 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Data type of Newtonian fluid model +! +!# Introduction +! +! This module defines a class [[NewtonianFluidModel_]] to +! model the fluid behavior. In addition, it defines a subroutine +! [[SetNewtonianFluidModelParam]] to Set the option +! to construct an instance of [[NewtonianFluidModel_]]. + +MODULE NewtonianFluidModel_Class +USE GlobalData +USE String_Class +USE BaSetype +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractMaterialModel_Class +USE AbstractFluidMechanicsModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "NewtonianFluidModel_CLASS" +CHARACTER(*), PARAMETER :: myprefix = "NewtonianFluidModel" +PUBLIC :: NewtonianFluidModel_ +PUBLIC :: TypeNewtonianFluidModel +PUBLIC :: NewtonianFluidModelPointer_ +PUBLIC :: SetNewtonianFluidModelParam + +!---------------------------------------------------------------------------- +! NewtonianFluidModel_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: A class for modeling Newtonian fluids +! +!# Introduction +! +! [[NewtonianFluidModel_]] class defines a Newtonian fluid. +! +! - `mu` represents the dynamicviscosity of the fluid. +! - dynamicViscosity $\mu$ of [[NewtonianFluidModel_]] is independent of the +! stress, and strain rate. +! - However, $\mu$ can depends upon the temperature, in case of +! non-isothermal fluid flow applications. +! +!@todo +! The dynamicviscosity of the fluid usually depends upon the temperature. +! Add this facility to the current class. +!@endtodo + +TYPE, EXTENDS(AbstractFluidMechanicsModel_) :: NewtonianFluidModel_ + PRIVATE + REAL(DFP) :: mu = 0.0_DFP +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: checkEssentialParam => & + & nfm_checkEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => nfm_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => nfm_Deallocate + FINAL :: nfm_FINAL + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => nfm_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => nfm_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => nfm_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetdynamicViscosity => & + & nfm_GetdynamicViscosity + PROCEDURE, PUBLIC, PASS(obj) :: GetModelParameters => & + & nfm_GetModelParameters + PROCEDURE, PUBLIC, PASS(obj) :: SetModelParameters => & + & nfm_SetModelParameters + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => nfm_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => nfm_GetParam + PROCEDURE, PUBLIC, PASS(obj) :: SetParam => nfm_SetParam +END TYPE NewtonianFluidModel_ + +TYPE(NewtonianFluidModel_), PARAMETER :: TypeNewtonianFluidModel = & + & NewtonianFluidModel_() + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE :: NewtonianFluidModelPointer_ + CLASS(NewtonianFluidModel_), POINTER :: ptr => NULL() +END TYPE NewtonianFluidModelPointer_ + +!---------------------------------------------------------------------------- +! SetNewtonianFluidModelParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Check the essential parameter +! +!# Introduction +! +! This routine Sets the options in `param` to construct an instance of +! [[NewtonianFluidModelPointer_]]. +! +!@note +! Always construct the parameter for [[NewtonianFluidModel_]] by using +! [[SetNewtonianFluidModelParam]] +!@endnote +! +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( ParameterList_ ) :: param +! CALL FPL_INIT; CALL param%initiate() +! CALL SetNewtonianFluidModelParam( param = param, dynamicViscosity=0.001_DFP ) +! CALL obj%initiate( param ) +! CALL param%print() +! CALL obj%display( msg="Test-1 : " ) +! CALL param%Deallocate(); CALL FPL_FINALIZE +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE SetNewtonianFluidModelParam(param, dynamicViscosity) + TYPE(ParameterList_), INTENT(INOUT) :: param + REAL(DFP), OPTIONAL, INTENT(IN) :: dynamicViscosity + END SUBROUTINE SetNewtonianFluidModelParam +END INTERFACE + +!---------------------------------------------------------------------------- +! checkEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Check the essential parameter +! +!# Introduction +! +! - This routine checks the availability of options in param +! - These options are necessary for constructing an instance of +! [[NewtonianFluidModel_]]. +! - This routine is called by [[NewtonianFluidModel_:Initiate]] + +INTERFACE + MODULE SUBROUTINE nfm_checkEssentialParam(obj, param) + CLASS(NewtonianFluidModel_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE nfm_checkEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: This routine initiates the the Newtonian fluid model +! +!# Introduction +! This routine initiates an instance of [[NewtonianFluidModel_]]. The usage +! is shown below. +! +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( ParameterList_ ) :: param +! CALL FPL_INIT; CALL param%initiate() +! CALL SetNewtonianFluidModelParam( param = param, & +! & dynamicViscosity=0.001_DFP ) +! CALL obj%initiate( param ) +! CALL param%print() +! CALL obj%display( msg="Test-1 : " ) +! CALL param%Deallocate(); CALL FPL_FINALIZE +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE nfm_Initiate(obj, param) + CLASS(NewtonianFluidModel_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE nfm_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Deallocate data stored in the object +! +!# Introduction +! +! This routine deallocates the memory occupied by [[NewtonianFluidModel_]] +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( ParameterList_ ) :: param +! CALL FPL_INIT; CALL param%initiate() +! CALL SetNewtonianFluidModelParam( param = param, & +! & dynamicViscosity=0.001_DFP ) +! CALL obj%initiate( param ) +! CALL param%print() +! CALL obj%display( msg="Test-1 : " ) +! CALL obj%Deallocate() +! CALL param%Deallocate(); CALL FPL_FINALIZE +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE nfm_Deallocate(obj) + CLASS(NewtonianFluidModel_), INTENT(INOUT) :: obj + END SUBROUTINE nfm_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Deallocate data stored in the object +! +!# Introduction +! +! This routine deallocates the memory occupied by [[NewtonianFluidModel_]] +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( ParameterList_ ) :: param +! CALL FPL_INIT; CALL param%initiate() +! CALL SetNewtonianFluidModelParam( param = param, & +! & dynamicViscosity=0.001_DFP ) +! CALL obj%initiate( param ) +! CALL param%print() +! CALL obj%display( msg="Test-1 : " ) +! CALL obj%Deallocate() +! CALL param%Deallocate(); CALL FPL_FINALIZE +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE nfm_Final(obj) + TYPE(NewtonianFluidModel_), INTENT(INOUT) :: obj + END SUBROUTINE nfm_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Initiate the Newtonian fluid model from hdf5 file +! +!# Introduction +! +! This routine initiates an instance of [[NewtonianFluidModel_]] by +! importing data from [[HDF5File_]] class. The content of [[HDF5File_]] +! is shown below. +! +! ![](../|media|/NewtonianFluidModel_template.png ""){: width="400"} +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( HDF5File_ ) :: hdf5file +! CALL hdf5file%initiate( "./TemplateNewtonianFluidModel1.hdf5", mode="READ") +! CALL hdf5file%open() +! CALL obj%import(hdf5file, "") +! CALL obj%Display("Test-3 : ") +! CALL hdf5file%close(); CALL hdf5file%Deallocate() +! CALL obj%Deallocate() +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE nfm_Import(obj, hdf5, group) + CLASS(NewtonianFluidModel_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE nfm_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Export the Newtonian fluid model to an hdf5 file +! +!# Introduction +! +! This routine exports the content of [[NewtonianFluidModel_]] in an +! [[HDF5File_]]. +! +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( ParameterList_ ) :: param +! TYPE( HDF5File_ ) :: hdf5file +! CALL FPL_INIT; CALL param%initiate() +! CALL SetNewtonianFluidModelParam( param = param, & +! & dynamicViscosity=0.001_DFP ) +! CALL obj%initiate( param ) +! CALL hdf5file%initiate( "./TemplateNewtonianFluidModel1.", mode="NEW ") +! CALL hdf5file%open() +! CALL obj%export(hdf5file, "") +! CALL hdf5file%close(); CALL hdf5file%Deallocate() +! CALL obj%Deallocate() +! CALL param%Deallocate(); CALL FPL_FINALIZE +! END PROGRAM main +!``` +! +! The above program generates a [[HDF5File_]], which is given below +! +! ![](../|media|/NewtonianFluidModel_template.png ""){: width="400"} +! + +INTERFACE + MODULE SUBROUTINE nfm_Export(obj, hdf5, group) + CLASS(NewtonianFluidModel_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE nfm_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Displays the content of Newtonian fluid model +! +!# Introduction +! +! This routine displays the content of [[NewtonianFluidModel_]] +! +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( ParameterList_ ) :: param +! CALL FPL_INIT; CALL param%initiate() +! CALL SetNewtonianFluidModelParam( param = param, & +! & dynamicViscosity=0.001_DFP ) +! CALL obj%initiate( param ) +! CALL param%print() +! CALL obj%display( msg="Test-1 : " ) +! CALL obj%Deallocate() +! CALL param%Deallocate(); CALL FPL_FINALIZE +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE nfm_Display(obj, msg, unitNo) + CLASS(NewtonianFluidModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE nfm_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetdynamicViscosity@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Returns the dynamicviscosity +! +!# Introduction +! +! This routine returns the [[NewtonianFluidModel_:mu]], & +! & dynamicviscosity $\mu$ +! +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! USE FPL, ONLY: ParameterList_ +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( HDF5File_ ) :: hdf5file +! TYPE( ParameterList_ ) :: param +! REAL( DFP ) :: dynamicViscosity +! CALL hdf5file%initiate( "./TemplateNewtonianFluidModel1.hdf5", mode="READ") +! CALL hdf5file%open() +! CALL obj%import(hdf5file, "") +! CALL obj%GetdynamicViscosity(dynamicViscosity=dynamicViscosity) +! CALL Display( dynamicViscosity, "dynamicViscosity : ") +! CALL FPL_INIT(); CALL param%initiate() +! CALL obj%GetModelParameters(param) +! CALL param%print() +! CALL FPL_FINALIZE(); CALL param%Deallocate() +! CALL hdf5file%close(); CALL hdf5file%Deallocate() +! CALL obj%Deallocate() +! END PROGRAM main +!``` + +INTERFACE + MODULE PURE SUBROUTINE nfm_GetdynamicViscosity(obj, dynamicViscosity) + CLASS(NewtonianFluidModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: dynamicViscosity + END SUBROUTINE nfm_GetdynamicViscosity +END INTERFACE + +!---------------------------------------------------------------------------- +! GetModelParameters@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Returns the model parameters in [[ParameterList_]] +! +!# Introduction +! +! This routine returns the model parameters in [[ParameterList_]] +! +! +!## Usage +! +!```fortran +! PROGRAM main +! USE easifemBase +! USE easifemClasses +! USE easifemMaterials +! USE FPL, ONLY: ParameterList_ +! IMPLICIT NONE +! TYPE( NewtonianFluidModel_ ) :: obj +! TYPE( HDF5File_ ) :: hdf5file +! TYPE( ParameterList_ ) :: param +! CALL hdf5file%initiate( "./TemplateNewtonianFluidModel1.hdf5", mode="READ") +! CALL hdf5file%open() +! CALL obj%import(hdf5file, "") +! CALL FPL_INIT(); CALL param%initiate() +! CALL obj%GetModelParameters(param) +! CALL param%print() +! CALL FPL_FINALIZE(); CALL param%Deallocate() +! CALL hdf5file%close(); CALL hdf5file%Deallocate() +! CALL obj%Deallocate() +! END PROGRAM main +!``` + +INTERFACE + MODULE SUBROUTINE nfm_GetModelParameters(obj, param) + CLASS(NewtonianFluidModel_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + END SUBROUTINE nfm_GetModelParameters +END INTERFACE + +!---------------------------------------------------------------------------- +! SetModelParameters@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: Sets the model parameters from param +! +!# Introduction +! +! This subroutine Sets the models parameter by reading them from param +! If an option is not available, then it does not Set that parameter. + +INTERFACE + MODULE SUBROUTINE nfm_SetModelParameters(obj, param) + CLASS(NewtonianFluidModel_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(INOUT) :: param + END SUBROUTINE nfm_SetModelParameters +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION nfm_GetPrefix(obj) RESULT(ans) + CLASS(NewtonianFluidModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION nfm_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! GetParam@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Get Parameters + +INTERFACE + MODULE SUBROUTINE nfm_GetParam(obj, dynamicViscosity) + CLASS(NewtonianFluidModel_), INTENT(IN) :: obj + REAL(DFP), OPTIONAL, INTENT(INOUT) :: dynamicViscosity + END SUBROUTINE nfm_GetParam +END INTERFACE + +!---------------------------------------------------------------------------- +! SetParam@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Set Parameters + +INTERFACE + MODULE SUBROUTINE nfm_SetParam(obj, dynamicViscosity) + CLASS(NewtonianFluidModel_), INTENT(INOUT) :: obj + REAL(DFP), OPTIONAL, INTENT(IN) :: dynamicViscosity + END SUBROUTINE nfm_SetParam +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE NewtonianFluidModel_Class From 940fa1fdc2071d7e24845cd5a498cc7f7eef043e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:36:56 +0900 Subject: [PATCH 073/117] Adding AbstractFluidMechnicsModel --- .../CMakeLists.txt | 22 +++++++++ .../src/AbstractFluidMechanicsModel_Class.F90 | 45 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/modules/AbstractFluidMechanicsModel/CMakeLists.txt create mode 100644 src/modules/AbstractFluidMechanicsModel/src/AbstractFluidMechanicsModel_Class.F90 diff --git a/src/modules/AbstractFluidMechanicsModel/CMakeLists.txt b/src/modules/AbstractFluidMechanicsModel/CMakeLists.txt new file mode 100644 index 000000000..aa3320838 --- /dev/null +++ b/src/modules/AbstractFluidMechanicsModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractFluidMechanicsModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/AbstractFluidMechanicsModel/src/AbstractFluidMechanicsModel_Class.F90 b/src/modules/AbstractFluidMechanicsModel/src/AbstractFluidMechanicsModel_Class.F90 new file mode 100644 index 000000000..3570fa90c --- /dev/null +++ b/src/modules/AbstractFluidMechanicsModel/src/AbstractFluidMechanicsModel_Class.F90 @@ -0,0 +1,45 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: A module for material behavior of fluids +! +!# Introduction +! +! This module defines an abstract class [[AbstractFluidMechanicsModel_]] +! for modeling the stres strain behavior of fluids. + +MODULE AbstractFluidMechanicsModel_Class +USE GlobalData, ONLY: I4B +USE AbstractMaterialModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "AbstractFluidMechanicsModel_Class" +INTEGER(I4B), PARAMETER, PUBLIC :: NewtonianFluidModel = 1 +INTEGER(I4B), PARAMETER, PUBLIC :: NonNewtonianFluidModel = 2 +PUBLIC :: AbstractFluidMechanicsModel_ + +!---------------------------------------------------------------------------- +! FluidMechanicsModel_ +!---------------------------------------------------------------------------- + +TYPE, ABSTRACT, EXTENDS(AbstractMaterialModel_) :: & + & AbstractFluidMechanicsModel_ +END TYPE AbstractFluidMechanicsModel_ + +END MODULE AbstractFluidMechanicsModel_Class From a91d294ebf63207039ee96e72a520078e713e814 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:37:09 +0900 Subject: [PATCH 074/117] Adding AbstractMaterialModel --- .../AbstractMaterialModel/CMakeLists.txt | 22 ++ .../src/AbstractMaterialModel_Class.F90 | 211 ++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 src/modules/AbstractMaterialModel/CMakeLists.txt create mode 100644 src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 diff --git a/src/modules/AbstractMaterialModel/CMakeLists.txt b/src/modules/AbstractMaterialModel/CMakeLists.txt new file mode 100644 index 000000000..95febee3f --- /dev/null +++ b/src/modules/AbstractMaterialModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractMaterialModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 new file mode 100644 index 000000000..fc6694c6b --- /dev/null +++ b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 @@ -0,0 +1,211 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Abstract class for Material Model + +MODULE AbstractMaterialModel_Class +USE GlobalData +USE BaseType +USE String_Class +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "AbstractMaterialModel_Class" +PUBLIC :: AbstractMaterialModel_ +PUBLIC :: AbstractMaterialModelPointer_ +PUBLIC :: AbstractMaterialModelDeallocate + +!---------------------------------------------------------------------------- +! AbstractMaterialModel_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: abstract class for modelling the behaviour of materials + +TYPE, ABSTRACT :: AbstractMaterialModel_ + LOGICAL(LGT) :: isInit = .FALSE. + TYPE(String) :: name +CONTAINS + PRIVATE + PROCEDURE(amb_CheckEssentialParam), DEFERRED, PUBLIC, PASS(obj) :: & + & CheckEssentialParam + PROCEDURE(amb_Initiate), DEFERRED, PUBLIC, PASS(obj) :: Initiate + PROCEDURE(amb_Deallocate), DEFERRED, PUBLIC, PASS(obj) :: & + & DEALLOCATE + PROCEDURE(amb_Import), DEFERRED, PUBLIC, PASS(obj) :: IMPORT + PROCEDURE(amb_Export), DEFERRED, PUBLIC, PASS(obj) :: Export + PROCEDURE(amb_Display), DEFERRED, PUBLIC, PASS(obj) :: Display + PROCEDURE(amb_GetPrefix), DEFERRED, PUBLIC, PASS(obj) :: GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: isInitiated => amb_isInitiated + PROCEDURE, PUBLIC, PASS(obj) :: GetName => amb_GetName + PROCEDURE, PUBLIC, PASS(obj) :: SetIsInitiated => amb_SetIsInitiated + PROCEDURE, PUBLIC, PASS(obj) :: SetName => amb_SetName +END TYPE AbstractMaterialModel_ + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE :: AbstractMaterialModelPointer_ + CLASS(AbstractMaterialModel_), POINTER :: ptr => NULL() +END TYPE AbstractMaterialModelPointer_ + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + SUBROUTINE amb_CheckEssentialParam(obj, param) + IMPORT :: AbstractMaterialModel_, ParameterList_ + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE amb_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + SUBROUTINE amb_Initiate(obj, param) + IMPORT :: AbstractMaterialModel_, ParameterList_ + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE amb_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + SUBROUTINE amb_Deallocate(obj) + IMPORT :: AbstractMaterialModel_ + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + END SUBROUTINE amb_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + SUBROUTINE amb_Import(obj, hdf5, group) + IMPORT :: AbstractMaterialModel_, HDF5File_ + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE amb_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + SUBROUTINE amb_Export(obj, hdf5, group) + IMPORT :: AbstractMaterialModel_, HDF5File_ + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE amb_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + SUBROUTINE amb_Display(obj, msg, unitNo) + IMPORT :: AbstractMaterialModel_, I4B + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE amb_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +ABSTRACT INTERFACE + FUNCTION amb_GetPrefix(obj) RESULT(ans) + IMPORT :: AbstractMaterialModel_ + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION amb_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! Contains +!---------------------------------------------------------------------------- + +CONTAINS + +SUBROUTINE AbstractMaterialModelDeallocate(obj) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + obj%name = "" + obj%isInit = .FALSE. +END SUBROUTINE AbstractMaterialModelDeallocate + +!---------------------------------------------------------------------------- +! GetName +!---------------------------------------------------------------------------- + +FUNCTION amb_GetName(obj) RESULT(ans) + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + ans = "" + ans = obj%name%chars() +END FUNCTION amb_GetName + +!---------------------------------------------------------------------------- +! isInitiated +!---------------------------------------------------------------------------- + +FUNCTION amb_isInitiated(obj) RESULT(ans) + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + ans = obj%isInit +END FUNCTION amb_isInitiated + +!---------------------------------------------------------------------------- +! isInitiated +!---------------------------------------------------------------------------- + +SUBROUTINE amb_SetIsInitiated(obj, VALUE) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: VALUE + obj%isInit = VALUE +END SUBROUTINE amb_SetIsInitiated + +!---------------------------------------------------------------------------- +! SetName +!---------------------------------------------------------------------------- + +SUBROUTINE amb_SetName(obj, VALUE) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: VALUE + obj%name = VALUE +END SUBROUTINE amb_SetName + +END MODULE AbstractMaterialModel_Class From bdda8b3d189ad478b02aad335091372906ffc73a Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:37:23 +0900 Subject: [PATCH 075/117] Adding AbstractSolidMechanicsModel --- .../AbstractPoroMechanicsModel/CMakeLists.txt | 22 ++++++++++ .../src/AbstractPoroMechanicsModel_Class.F90 | 42 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/modules/AbstractPoroMechanicsModel/CMakeLists.txt create mode 100644 src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 diff --git a/src/modules/AbstractPoroMechanicsModel/CMakeLists.txt b/src/modules/AbstractPoroMechanicsModel/CMakeLists.txt new file mode 100644 index 000000000..d532451cc --- /dev/null +++ b/src/modules/AbstractPoroMechanicsModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractPoroMechanicsModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 b/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 new file mode 100644 index 000000000..2e2a1f223 --- /dev/null +++ b/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 @@ -0,0 +1,42 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Abstract class for Material behavior of porous media + +MODULE AbstractPoroMechanicsModel_Class +USE AbstractSolidMechanicsModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "AbstractPoroMechanicsModel_Class" + +PUBLIC :: IsoLinearElasticModel +PUBLIC :: AnisoLinearElasticModel +PUBLIC :: OrthoLinearElasticModel +PUBLIC :: TransLinearElasticModel +PUBLIC :: AbstractPoroMechanicsModel_ + +!---------------------------------------------------------------------------- +! SolidMechanicsModel_ +!---------------------------------------------------------------------------- + +TYPE, ABSTRACT, EXTENDS(AbstractSolidMechanicsModel_) :: & + & AbstractPoroMechanicsModel_ +END TYPE AbstractPoroMechanicsModel_ + +END MODULE AbstractPoroMechanicsModel_Class From d7192cd06aed6f9202eb870930da5f6039a2ee32 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:37:37 +0900 Subject: [PATCH 076/117] Adding AbstractSolidMechanicsModel --- .../CMakeLists.txt | 22 ++ .../src/AbstractSolidMechanicsModel_Class.F90 | 278 ++++++++++++++++++ 2 files changed, 300 insertions(+) create mode 100644 src/modules/AbstractSolidMechanicsModel/CMakeLists.txt create mode 100644 src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 diff --git a/src/modules/AbstractSolidMechanicsModel/CMakeLists.txt b/src/modules/AbstractSolidMechanicsModel/CMakeLists.txt new file mode 100644 index 000000000..3923519f1 --- /dev/null +++ b/src/modules/AbstractSolidMechanicsModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractSolidMechanicsModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 b/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 new file mode 100644 index 000000000..2a9b25602 --- /dev/null +++ b/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 @@ -0,0 +1,278 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Abstract class for Material behavior + +MODULE AbstractSolidMechanicsModel_Class +USE GlobalData, ONLY: I4B, LGT, DFP, CHAR_LF +USE String_Class +USE BaseType +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractMaterialModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "AbstractSolidMechanicsModel_Class" +PUBLIC :: AbstractSolidMechanicsModel_ +PUBLIC :: AbstractSolidMechanicsModelDeallocate + +INTEGER(I4B), PARAMETER, PUBLIC :: IsoLinearElasticModel = 1 +INTEGER(I4B), PARAMETER, PUBLIC :: AnisoLinearElasticModel = 2 +INTEGER(I4B), PARAMETER, PUBLIC :: OrthoLinearElasticModel = 3 +INTEGER(I4B), PARAMETER, PUBLIC :: TransLinearElasticModel = 4 + +!---------------------------------------------------------------------------- +! AbstractSolidMechanicsModel_ +!---------------------------------------------------------------------------- + +TYPE, ABSTRACT, EXTENDS(AbstractMaterialModel_) :: & + & AbstractSolidMechanicsModel_ + PRIVATE + LOGICAL(LGT) :: isPStress = .FALSE. + !! PlaneStress + LOGICAL(LGT) :: isPStrain = .FALSE. + !! PlaneStrain +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & lem_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => lem_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => lem_Deallocate + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => lem_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => lem_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => lem_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticParam => lem_GetElasticParam + PROCEDURE, PUBLIC, PASS(obj) :: GetC => lem_GetC + PROCEDURE, PUBLIC, PASS(obj) :: GetInvC => lem_GetInvC + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticityType => & + & lem_GetElasticityType + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => lem_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: isPlaneStrain => lem_isPlaneStrain + PROCEDURE, PUBLIC, PASS(obj) :: isPlaneStress => lem_isPlaneStress + PROCEDURE, PUBLIC, PASS(obj) :: SetPlaneStress => lem_SetPlaneStress + PROCEDURE, PUBLIC, PASS(obj) :: SetPlaneStrain => lem_SetPlaneStrain +END TYPE AbstractSolidMechanicsModel_ + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Check the essential parameter + +INTERFACE + MODULE SUBROUTINE lem_CheckEssentialParam(obj, param) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE lem_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the the Linear elastic model + +INTERFACE + MODULE SUBROUTINE lem_Initiate(obj, param) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE lem_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Deallocate data + +INTERFACE + MODULE SUBROUTINE lem_Deallocate(obj) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + END SUBROUTINE lem_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Initiate the linear elastic model by import + +INTERFACE + MODULE SUBROUTINE lem_Import(obj, hdf5, group) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE lem_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Export the linear elastic model + +INTERFACE + MODULE SUBROUTINE lem_Export(obj, hdf5, group) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE lem_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Displays the content of linear elastic model + +INTERFACE + MODULE SUBROUTINE lem_Display(obj, msg, unitNo) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE lem_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticParam@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE lem_GetElasticParam(obj, PoissonRatio, & + & ShearModulus, lambda, YoungsModulus, stiffnessPower) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + REAL(DFP), OPTIONAL, INTENT(INOUT) :: PoissonRatio + REAL(DFP), OPTIONAL, INTENT(INOUT) :: ShearModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: lambda + REAL(DFP), OPTIONAL, INTENT(INOUT) :: YoungsModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: stiffnessPower + END SUBROUTINE lem_GetElasticParam +END INTERFACE + +!---------------------------------------------------------------------------- +! GetC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE lem_GetC(obj, C) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: C(:, :) + END SUBROUTINE lem_GetC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE lem_GetInvC(obj, InvC) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: InvC(:, :) + END SUBROUTINE lem_GetInvC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticityType@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION lem_GetElasticityType(obj) RESULT(Ans) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION lem_GetElasticityType +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION lem_GetPrefix(obj) RESULT(ans) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION lem_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! Contains +!---------------------------------------------------------------------------- + +CONTAINS + +SUBROUTINE AbstractSolidMechanicsModelDeallocate(obj) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + CALL AbstractMaterialModelDeallocate(obj) + obj%isPStress = .FALSE. + obj%isPStrain = .FALSE. +END SUBROUTINE AbstractSolidMechanicsModelDeallocate + +!---------------------------------------------------------------------------- +! isPlaneStress +!---------------------------------------------------------------------------- + +FUNCTION lem_isPlaneStress(obj) RESULT(ans) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + ans = obj%isPStress +END FUNCTION lem_isPlaneStress + +!---------------------------------------------------------------------------- +! isPlaneStrain +!---------------------------------------------------------------------------- + +FUNCTION lem_isPlaneStrain(obj) RESULT(ans) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + ans = obj%isPStrain +END FUNCTION lem_isPlaneStrain + +!---------------------------------------------------------------------------- +! SetPlaneStress +!---------------------------------------------------------------------------- + +SUBROUTINE lem_SetPlaneStress(obj, VALUE) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: VALUE + obj%isPStress = VALUE +END SUBROUTINE lem_SetPlaneStress + +!---------------------------------------------------------------------------- +! SetPlaneStrain +!---------------------------------------------------------------------------- + +SUBROUTINE lem_SetPlaneStrain(obj, VALUE) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: VALUE + obj%isPStrain = VALUE +END SUBROUTINE lem_SetPlaneStrain + +END MODULE AbstractSolidMechanicsModel_Class From 1f74cbc46a970d5328340f44f08726fb6b000891 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:37:56 +0900 Subject: [PATCH 077/117] Adding easifemMaterials --- src/modules/easifemMaterials/CMakeLists.txt | 22 +++++++++ .../easifemMaterials/src/easifemMaterials.F90 | 47 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/modules/easifemMaterials/CMakeLists.txt create mode 100644 src/modules/easifemMaterials/src/easifemMaterials.F90 diff --git a/src/modules/easifemMaterials/CMakeLists.txt b/src/modules/easifemMaterials/CMakeLists.txt new file mode 100644 index 000000000..81c9976b0 --- /dev/null +++ b/src/modules/easifemMaterials/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/easifemMaterials.F90 +) \ No newline at end of file diff --git a/src/modules/easifemMaterials/src/easifemMaterials.F90 b/src/modules/easifemMaterials/src/easifemMaterials.F90 new file mode 100644 index 000000000..19b34dde4 --- /dev/null +++ b/src/modules/easifemMaterials/src/easifemMaterials.F90 @@ -0,0 +1,47 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This module contains the content of `libeasifemMaterials` +! +!# Introduction +! +! This is the module which a user should use to get the content of +! `libeasifemMaterials` +! +! +!## Usage +! +!```fortran +! USE easifemMaterials +!``` + +MODULE easifemMaterials +USE AbstractMaterialModel_Class +USE AbstractSolidMechanicsModel_Class +USE AbstractPoroMechanicsModel_Class +USE AbstractFluidMechanicsModel_Class +USE LinearElasticModel_Class +USE LinearPoroElasticModel_Class +USE NewtonianFluidModel_Class +USE AbstractMaterial_Class +USE SolidMaterial_Class +USE FluidMaterial_Class +USE PorousMaterial_Class +USE MaterialFactory +END MODULE easifemMaterials From 7d3fb1a13d3661cd8e9027cecc2f8a38f94ba4fd Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:38:04 +0900 Subject: [PATCH 078/117] Adding easifemClasses --- src/modules/easifemClasses/src/easifemClasses.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/easifemClasses/src/easifemClasses.F90 b/src/modules/easifemClasses/src/easifemClasses.F90 index 0f3b40bbd..3d84e8327 100644 --- a/src/modules/easifemClasses/src/easifemClasses.F90 +++ b/src/modules/easifemClasses/src/easifemClasses.F90 @@ -68,4 +68,6 @@ MODULE easifemClasses ! USE ogpf USE TomlUtility + +USE easifemMaterials END MODULE easifemClasses From db3ef2d09eca167f589c67ab6307a007f1816825 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:38:18 +0900 Subject: [PATCH 079/117] Adding LinearElasticModel --- src/modules/FluidMaterial/CMakeLists.txt | 22 ++ .../FluidMaterial/src/FluidMaterial_Class.F90 | 231 ++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 src/modules/FluidMaterial/CMakeLists.txt create mode 100644 src/modules/FluidMaterial/src/FluidMaterial_Class.F90 diff --git a/src/modules/FluidMaterial/CMakeLists.txt b/src/modules/FluidMaterial/CMakeLists.txt new file mode 100644 index 000000000..4fda26972 --- /dev/null +++ b/src/modules/FluidMaterial/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/FluidMaterial_Class.F90 +) \ No newline at end of file diff --git a/src/modules/FluidMaterial/src/FluidMaterial_Class.F90 b/src/modules/FluidMaterial/src/FluidMaterial_Class.F90 new file mode 100644 index 000000000..da3a39707 --- /dev/null +++ b/src/modules/FluidMaterial/src/FluidMaterial_Class.F90 @@ -0,0 +1,231 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 2 Oct 2021 +! summary: This module defines a class called [[FluidMaterial_]] +! +!# Introduction +! +! This module defines a class called [[FluidMaterial_]], which +! defines a fluid material and its behavior. +! Other than defining the class, this module makes a routine called +! [[FluidMaterial_Class:SetFluidMaterialParam]] public. This routine +! can be used for Setting the options in [[ParameterList_]] object. +! + +MODULE FluidMaterial_Class +USE GlobalData +USE String_Class +USE BaSetype +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractMaterial_Class +USE AbstractFluidMechanicsModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "FluidMaterial_Class" +CHARACTER(*), PARAMETER :: myprefix = "FluidMaterial" +PUBLIC :: FluidMaterial_ +PUBLIC :: TypeFluidMaterial +PUBLIC :: FluidMaterialPointer_ +PUBLIC :: SetFluidMaterialParam + +!---------------------------------------------------------------------------- +! FluidMaterial_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 1 Oct 2021 +! summary: This data type define a fluid material and its behavior + +TYPE, EXTENDS(AbstractMaterial_) :: FluidMaterial_ + CLASS(AbstractFluidMechanicsModel_), POINTER :: stressStrainModel => NULL() + !! Pointer to stress strain material behavior of fluid + !! It defines the rheology of the fluid. +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & fluid_CheckEssentialParam + !! Check the essential parameter + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => fluid_Initiate + !! Initiate an instance of [[FluidMaterial_]] + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => fluid_Deallocate + !! Deallocate the memory occupied by the instance of [[FluidMaterial_]] + FINAL :: fluid_Final + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => fluid_Import + !! Initiate the instance by importing data from [[HDF5File_]] object + PROCEDURE, PUBLIC, PASS(obj) :: Export => fluid_Export + !! Export the data of [[FluidMaterial_]] to [[HDF5File_]] object + PROCEDURE, PUBLIC, PASS(obj) :: Display => fluid_Display + !! Display the content of [[FluidMaterial_]] + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => fluid_GetPrefix +END TYPE FluidMaterial_ + +TYPE(FluidMaterial_), PARAMETER :: TypeFluidMaterial = FluidMaterial_() + +!---------------------------------------------------------------------------- +! FluidMaterialPointer_ +!---------------------------------------------------------------------------- + +TYPE :: FluidMaterialPointer_ + CLASS(FluidMaterial_), POINTER :: ptr => NULL() +END TYPE FluidMaterialPointer_ + +!---------------------------------------------------------------------------- +! SetFluidMaterialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine Sets options for constructing [[FluidMaterial_]] +! + +INTERFACE + MODULE SUBROUTINE SetFluidMaterialParam(param, name, stressStrainModel) + TYPE(ParameterList_), INTENT(INOUT) :: param + CHARACTER(*), INTENT(IN) :: name + !! It is the name of the material + CHARACTER(*), OPTIONAL, INTENT(IN) :: stressStrainModel + !! Name of the child-class of `AbstractSolidMechanicsModel_` + !! For example `LinearElasticModel` + END SUBROUTINE SetFluidMaterialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine Checks the essential parameter + +INTERFACE + MODULE SUBROUTINE fluid_CheckEssentialParam(obj, param) + CLASS(FluidMaterial_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE fluid_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the instance of `Solid` + +INTERFACE + MODULE SUBROUTINE fluid_Initiate(obj, param, prefix) + CLASS(FluidMaterial_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + CHARACTER(*), OPTIONAL, INTENT(IN) :: prefix + END SUBROUTINE fluid_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine deallocates the instance + +INTERFACE + MODULE SUBROUTINE fluid_Deallocate(obj) + CLASS(FluidMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE fluid_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine deallocates the instance + +INTERFACE + MODULE SUBROUTINE fluid_Final(obj) + TYPE(FluidMaterial_), INTENT(INOUT) :: obj + END SUBROUTINE fluid_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the instance from hdf5 file + +INTERFACE + MODULE SUBROUTINE fluid_Import(obj, hdf5, group) + CLASS(FluidMaterial_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE fluid_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine exports the information to external hdf5 file + +INTERFACE + MODULE SUBROUTINE fluid_Export(obj, hdf5, group) + CLASS(FluidMaterial_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE fluid_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine displays the content of the instance + +INTERFACE + MODULE SUBROUTINE fluid_Display(obj, msg, unitNo) + CLASS(FluidMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE fluid_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION fluid_GetPrefix(obj) RESULT(ans) + CLASS(FluidMaterial_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION fluid_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE FluidMaterial_Class From 94bc9147f82a73d3d93f0bdfb492bc2fd25745cc Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:38:31 +0900 Subject: [PATCH 080/117] Adding LinearPoroElasticModel --- src/modules/LinearElasticModel/CMakeLists.txt | 22 + .../src/LinearElasticModel_Class.F90 | 397 ++++++++++++++++++ 2 files changed, 419 insertions(+) create mode 100644 src/modules/LinearElasticModel/CMakeLists.txt create mode 100644 src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 diff --git a/src/modules/LinearElasticModel/CMakeLists.txt b/src/modules/LinearElasticModel/CMakeLists.txt new file mode 100644 index 000000000..de10be889 --- /dev/null +++ b/src/modules/LinearElasticModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/LinearElasticModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 b/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 new file mode 100644 index 000000000..4cba29723 --- /dev/null +++ b/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 @@ -0,0 +1,397 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Data type of linear elastic model + +MODULE LinearElasticModel_Class +USE GlobalData +USE String_Class +USE BaseType +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractSolidMechanicsModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "LinearElasticModel_Class" +CHARACTER(*), PARAMETER :: myprefix = "LinearElasticModel" +PUBLIC :: LinearElasticModel_ +PUBLIC :: TypeLinearElasticModel +PUBLIC :: LinearElasticModelPointer_ +PUBLIC :: SetLinearElasticModelParam +PUBLIC :: GetElasticParam +PUBLIC :: Get_PlaneStress_C_InvC +PUBLIC :: Get_PlaneStrain_C_InvC +PUBLIC :: Get_3D_C_InvC + +!---------------------------------------------------------------------------- +! LinearElasticModel_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Datatype for modeling Linear elastic behavior of solids + +TYPE, EXTENDS(AbstractSolidMechanicsModel_) :: LinearElasticModel_ + PRIVATE + INTEGER(I4B) :: elasticityType = 0 + REAL(DFP) :: nu = 0.0_DFP + REAL(DFP) :: G = 0.0_DFP + REAL(DFP) :: E = 0.0_DFP + REAL(DFP) :: lambda = 0.0_DFP + REAL(DFP) :: C(6, 6) = 0.0_DFP + REAL(DFP) :: invC(6, 6) = 0.0_DFP + REAL(DFP) :: stiffnessPower = 0.0_DFP +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & lem_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => lem_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => lem_Deallocate + FINAL :: lem_FINAL + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => lem_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => lem_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => lem_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticParam => lem_GetElasticParam + PROCEDURE, PUBLIC, PASS(obj) :: GetC => lem_GetC + PROCEDURE, PUBLIC, PASS(obj) :: GetInvC => lem_GetInvC + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticityType => & + & lem_GetElasticityType + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => & + & lem_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => & + & lem_GetParam + PROCEDURE, PUBLIC, PASS(obj) :: SetParam => & + & lem_SetParam +END TYPE LinearElasticModel_ + +TYPE(LinearElasticModel_), PARAMETER :: TypeLinearElasticModel = & + & LinearElasticModel_() + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE :: LinearElasticModelPointer_ + CLASS(LinearElasticModel_), POINTER :: ptr => NULL() +END TYPE LinearElasticModelPointer_ + +!---------------------------------------------------------------------------- +! SetLinearElasticModelParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Check the essential parameter + +INTERFACE + MODULE SUBROUTINE SetLinearElasticModelParam(param, elasticityType, & + & isPlaneStrain, isPlaneStress, poissonRatio, youngsModulus, & + & shearModulus, lambda, C, invC, stiffnessPower) + TYPE(ParameterList_), INTENT(INOUT) :: param + INTEGER(I4B), INTENT(IN) :: elasticityType + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isPlaneStress + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isPlaneStrain + REAL(DFP), OPTIONAL, INTENT(IN) :: poissonRatio + REAL(DFP), OPTIONAL, INTENT(IN) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: shearModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: lambda + REAL(DFP), OPTIONAL, INTENT(IN) :: C(6, 6) + REAL(DFP), OPTIONAL, INTENT(IN) :: invC(6, 6) + REAL(DFP), OPTIONAL, INTENT(IN) :: stiffnessPower + END SUBROUTINE SetLinearElasticModelParam +END INTERFACE + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Check the essential parameter + +INTERFACE + MODULE SUBROUTINE lem_CheckEssentialParam(obj, param) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE lem_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This routine initiates the the Linear elastic model + +INTERFACE + MODULE SUBROUTINE lem_Initiate(obj, param) + CLASS(LinearElasticModel_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE lem_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Deallocate data + +INTERFACE + MODULE SUBROUTINE lem_Deallocate(obj) + CLASS(LinearElasticModel_), INTENT(INOUT) :: obj + END SUBROUTINE lem_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Deallocate data + +INTERFACE + MODULE SUBROUTINE lem_Final(obj) + TYPE(LinearElasticModel_), INTENT(INOUT) :: obj + END SUBROUTINE lem_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Initiate the linear elastic model by import + +INTERFACE + MODULE SUBROUTINE lem_Import(obj, hdf5, group) + CLASS(LinearElasticModel_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE lem_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Export the linear elastic model + +INTERFACE + MODULE SUBROUTINE lem_Export(obj, hdf5, group) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE lem_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: Displays the content of linear elastic model + +INTERFACE + MODULE SUBROUTINE lem_Display(obj, msg, unitNo) + CLASS(LinearElasticModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE lem_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticParameter@GetMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This returns the elastic parameter + +INTERFACE + MODULE SUBROUTINE GetElasticParam(lam, G, EE, nu, shearModulus, & + & youngsModulus, poissonRatio, lambda) + REAL(DFP), INTENT(OUT) :: lam + REAL(DFP), INTENT(OUT) :: G + REAL(DFP), INTENT(OUT) :: EE + REAL(DFP), INTENT(OUT) :: nu + REAL(DFP), OPTIONAL, INTENT(IN) :: shearModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: poissonRatio + REAL(DFP), OPTIONAL, INTENT(IN) :: lambda + END SUBROUTINE GetElasticParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Get_PlaneStress_C_InvC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE Get_PlaneStress_C_InvC(C, invC, youngsModulus, nu) + REAL(DFP), INTENT(INOUT) :: C(:, :) + REAL(DFP), INTENT(INOUT) :: invC(:, :) + REAL(DFP), INTENT(IN) :: youngsModulus + REAL(DFP), INTENT(IN) :: nu + END SUBROUTINE Get_PlaneStress_C_InvC +END INTERFACE + +!---------------------------------------------------------------------------- +! Get_PlaneStrain_C_InvC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE Get_PlaneStrain_C_InvC(C, invC, youngsModulus, nu) + REAL(DFP), INTENT(INOUT) :: C(:, :) + REAL(DFP), INTENT(INOUT) :: invC(:, :) + REAL(DFP), INTENT(IN) :: youngsModulus + REAL(DFP), INTENT(IN) :: nu + END SUBROUTINE Get_PlaneStrain_C_InvC +END INTERFACE + +!---------------------------------------------------------------------------- +! Get_3D_C_InvC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE Get_3D_C_InvC(C, invC, youngsModulus, nu) + REAL(DFP), INTENT(INOUT) :: C(:, :) + REAL(DFP), INTENT(INOUT) :: invC(:, :) + REAL(DFP), INTENT(IN) :: youngsModulus + REAL(DFP), INTENT(IN) :: nu + END SUBROUTINE Get_3D_C_InvC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticParam@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE lem_GetElasticParam(obj, poissonRatio, & + & shearModulus, lambda, youngsModulus, stiffnessPower) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + REAL(DFP), OPTIONAL, INTENT(INOUT) :: poissonRatio + REAL(DFP), OPTIONAL, INTENT(INOUT) :: shearModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: lambda + REAL(DFP), OPTIONAL, INTENT(INOUT) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: stiffnessPower + END SUBROUTINE lem_GetElasticParam +END INTERFACE + +!---------------------------------------------------------------------------- +! GetC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE lem_GetC(obj, C) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: C(:, :) + END SUBROUTINE lem_GetC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE lem_GetInvC(obj, InvC) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: InvC(:, :) + END SUBROUTINE lem_GetInvC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticityType@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION lem_GetElasticityType(obj) RESULT(Ans) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION lem_GetElasticityType +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION lem_GetPrefix(obj) RESULT(ans) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION lem_GetPrefix +END INTERFACE + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Set param + +INTERFACE + MODULE SUBROUTINE lem_SetParam(obj, elasticityType, & + & nu, G, youngsModulus, lambda, C, invC, stiffnessPower) + CLASS(LinearElasticModel_), INTENT(INOUT) :: obj + INTEGER(I4B), OPTIONAL, INTENT(IN) :: elasticityType + REAL(DFP), OPTIONAL, INTENT(IN) :: nu + REAL(DFP), OPTIONAL, INTENT(IN) :: G + REAL(DFP), OPTIONAL, INTENT(IN) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: lambda + REAL(DFP), OPTIONAL, INTENT(IN) :: C(6, 6) + REAL(DFP), OPTIONAL, INTENT(IN) :: invC(6, 6) + REAL(DFP), OPTIONAL, INTENT(IN) :: stiffnessPower + END SUBROUTINE lem_SetParam +END INTERFACE + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Get param + +INTERFACE + MODULE SUBROUTINE lem_GetParam(obj, elasticityType, & + & nu, G, youngsModulus, lambda, C, invC, stiffnessPower) + CLASS(LinearElasticModel_), INTENT(IN) :: obj + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: elasticityType + REAL(DFP), OPTIONAL, INTENT(INOUT) :: nu + REAL(DFP), OPTIONAL, INTENT(INOUT) :: G + REAL(DFP), OPTIONAL, INTENT(INOUT) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: lambda + REAL(DFP), OPTIONAL, INTENT(INOUT) :: C(6, 6) + REAL(DFP), OPTIONAL, INTENT(INOUT) :: invC(6, 6) + REAL(DFP), OPTIONAL, INTENT(INOUT) :: stiffnessPower + END SUBROUTINE lem_GetParam +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE LinearElasticModel_Class From 0320e458dbf598bde7c662a477c4f74ef235254a Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:38:43 +0900 Subject: [PATCH 081/117] Adding LinearPoroElasticModel --- .../LinearPoroElasticModel/CMakeLists.txt | 22 ++ .../src/LinearPoroElasticModel_Class.F90 | 315 ++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 src/modules/LinearPoroElasticModel/CMakeLists.txt create mode 100644 src/modules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class.F90 diff --git a/src/modules/LinearPoroElasticModel/CMakeLists.txt b/src/modules/LinearPoroElasticModel/CMakeLists.txt new file mode 100644 index 000000000..a481a8b1e --- /dev/null +++ b/src/modules/LinearPoroElasticModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/LinearPoroElasticModel_Class.F90 +) \ No newline at end of file diff --git a/src/modules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class.F90 b/src/modules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class.F90 new file mode 100644 index 000000000..6ae923fd2 --- /dev/null +++ b/src/modules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class.F90 @@ -0,0 +1,315 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Data type of linear elastic model + +MODULE LinearPoroElasticModel_Class +USE GlobalData +USE String_Class +USE BaSetype +USE ExceptionHandler_Class, ONLY: e +USE HDF5File_Class +USE FPL, ONLY: ParameterList_ +USE AbstractPoroMechanicsModel_Class +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "LinearPoroElasticModel_Class" +CHARACTER(*), PARAMETER :: myPrefix = "LinearPoroElasticModel" +PUBLIC :: LinearPoroElasticModel_ +PUBLIC :: TypeLinearPoroElasticModel +PUBLIC :: LinearPoroElasticModelPointer_ +PUBLIC :: SetLinearPoroElasticModelParam + +!---------------------------------------------------------------------------- +! LinearPoroElasticModel_ +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Datatype for modeling Linear elastic behavior of [[PorousMaterial_]] + +TYPE, EXTENDS(AbstractPoroMechanicsModel_) :: LinearPoroElasticModel_ + PRIVATE + INTEGER(I4B) :: elasticityType = 0 + REAL(DFP) :: nu = 0.0_DFP + REAL(DFP) :: G = 0.0_DFP + REAL(DFP) :: E = 0.0_DFP + REAL(DFP) :: lambda = 0.0_DFP + REAL(DFP) :: C(6, 6) = 0.0_DFP + REAL(DFP) :: invC(6, 6) = 0.0_DFP +CONTAINS + PRIVATE + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & lpem_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => lpem_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => lpem_Deallocate + FINAL :: lpem_FINAL + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => lpem_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => lpem_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => lpem_Display + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticParam => lpem_GetElasticParam + PROCEDURE, PUBLIC, PASS(obj) :: GetC => lpem_GetC + PROCEDURE, PUBLIC, PASS(obj) :: GetInvC => lpem_GetInvC + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticityType => & + & lpem_GetElasticityType + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => & + & lpem_GetParam + PROCEDURE, PUBLIC, PASS(obj) :: SetParam => & + & lpem_SetParam +END TYPE LinearPoroElasticModel_ + +TYPE(LinearPoroElasticModel_), PARAMETER :: TypeLinearPoroElasticModel & + & = LinearPoroElasticModel_() + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE :: LinearPoroElasticModelPointer_ + CLASS(LinearPoroElasticModel_), POINTER :: ptr => NULL() +END TYPE LinearPoroElasticModelPointer_ + +!---------------------------------------------------------------------------- +! SetLinearPoroElasticModelParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Check the essential parameter + +INTERFACE + MODULE SUBROUTINE SetLinearPoroElasticModelParam(param, elasticityType, & + & isPlaneStrain, isPlaneStress, PoissonRatio, YoungsModulus, & + & ShearModulus, lambda, C, invC) + TYPE(ParameterList_), INTENT(INOUT) :: param + INTEGER(I4B), INTENT(IN) :: elasticityType + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isPlaneStress + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isPlaneStrain + REAL(DFP), OPTIONAL, INTENT(IN) :: PoissonRatio + REAL(DFP), OPTIONAL, INTENT(IN) :: YoungsModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: ShearModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: lambda + REAL(DFP), OPTIONAL, INTENT(IN) :: C(6, 6) + REAL(DFP), OPTIONAL, INTENT(IN) :: invC(6, 6) + END SUBROUTINE SetLinearPoroElasticModelParam +END INTERFACE + +!---------------------------------------------------------------------------- +! CheckEssentialParam@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Check the essential parameter + +INTERFACE + MODULE SUBROUTINE lpem_CheckEssentialParam(obj, param) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE lpem_CheckEssentialParam +END INTERFACE + +!---------------------------------------------------------------------------- +! Initiate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: This routine initiates the the Linear elastic model + +INTERFACE + MODULE SUBROUTINE lpem_Initiate(obj, param) + CLASS(LinearPoroElasticModel_), INTENT(INOUT) :: obj + TYPE(ParameterList_), INTENT(IN) :: param + END SUBROUTINE lpem_Initiate +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Deallocate data + +INTERFACE + MODULE SUBROUTINE lpem_Deallocate(obj) + CLASS(LinearPoroElasticModel_), INTENT(INOUT) :: obj + END SUBROUTINE lpem_Deallocate +END INTERFACE + +!---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Deallocate data + +INTERFACE + MODULE SUBROUTINE lpem_Final(obj) + TYPE(LinearPoroElasticModel_), INTENT(INOUT) :: obj + END SUBROUTINE lpem_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! Import@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Initiate the linear elastic model by import + +INTERFACE + MODULE SUBROUTINE lpem_Import(obj, hdf5, group) + CLASS(LinearPoroElasticModel_), INTENT(INOUT) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE lpem_Import +END INTERFACE + +!---------------------------------------------------------------------------- +! Export@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Export the linear elastic model + +INTERFACE + MODULE SUBROUTINE lpem_Export(obj, hdf5, group) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + TYPE(HDF5File_), INTENT(INOUT) :: hdf5 + CHARACTER(*), INTENT(IN) :: group + END SUBROUTINE lpem_Export +END INTERFACE + +!---------------------------------------------------------------------------- +! Display@IOMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 4 Oct 2021 +! summary: Displays the content of linear elastic model + +INTERFACE + MODULE SUBROUTINE lpem_Display(obj, msg, unitNo) + CLASS(LinearPoroElasticModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: msg + INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo + END SUBROUTINE lpem_Display +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticParam@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE PURE SUBROUTINE lpem_GetElasticParam(obj, PoissonRatio, & + & ShearModulus, lambda, YoungsModulus, stiffnessPower) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + REAL(DFP), OPTIONAL, INTENT(INOUT) :: PoissonRatio + REAL(DFP), OPTIONAL, INTENT(INOUT) :: ShearModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: lambda + REAL(DFP), OPTIONAL, INTENT(INOUT) :: YoungsModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: stiffnessPower + END SUBROUTINE lpem_GetElasticParam +END INTERFACE + +!---------------------------------------------------------------------------- +! GetC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE PURE SUBROUTINE lpem_GetC(obj, C) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: C(:, :) + END SUBROUTINE lpem_GetC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetC@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE PURE SUBROUTINE lpem_GetInvC(obj, InvC) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + REAL(DFP), INTENT(INOUT) :: InvC(:, :) + END SUBROUTINE lpem_GetInvC +END INTERFACE + +!---------------------------------------------------------------------------- +! GetElasticityType@GetMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE PURE FUNCTION lpem_GetElasticityType(obj) RESULT(Ans) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION lpem_GetElasticityType +END INTERFACE + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Set param + +INTERFACE + MODULE SUBROUTINE lpem_SetParam(obj, elasticityType, & + & nu, G, youngsModulus, lambda, C, invC) + CLASS(LinearPoroElasticModel_), INTENT(INOUT) :: obj + INTEGER(I4B), OPTIONAL, INTENT(IN) :: elasticityType + REAL(DFP), OPTIONAL, INTENT(IN) :: nu + REAL(DFP), OPTIONAL, INTENT(IN) :: G + REAL(DFP), OPTIONAL, INTENT(IN) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(IN) :: lambda + REAL(DFP), OPTIONAL, INTENT(IN) :: C(6, 6) + REAL(DFP), OPTIONAL, INTENT(IN) :: invC(6, 6) + END SUBROUTINE lpem_SetParam +END INTERFACE + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-22 +! summary: Get param + +INTERFACE + MODULE SUBROUTINE lpem_GetParam(obj, elasticityType, & + & nu, G, youngsModulus, lambda, C, invC) + CLASS(LinearPoroElasticModel_), INTENT(IN) :: obj + INTEGER(I4B), OPTIONAL, INTENT(INOUT) :: elasticityType + REAL(DFP), OPTIONAL, INTENT(INOUT) :: nu + REAL(DFP), OPTIONAL, INTENT(INOUT) :: G + REAL(DFP), OPTIONAL, INTENT(INOUT) :: youngsModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: lambda + REAL(DFP), OPTIONAL, INTENT(INOUT) :: C(6, 6) + REAL(DFP), OPTIONAL, INTENT(INOUT) :: invC(6, 6) + END SUBROUTINE lpem_GetParam +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE LinearPoroElasticModel_Class From b80ebda39618680d5f56e56630c3be465f802f1e Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:38:52 +0900 Subject: [PATCH 082/117] Adding MaterialFactory --- src/modules/MaterialFactory/CMakeLists.txt | 22 ++++ .../MaterialFactory/src/MaterialFactory.F90 | 110 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/modules/MaterialFactory/CMakeLists.txt create mode 100644 src/modules/MaterialFactory/src/MaterialFactory.F90 diff --git a/src/modules/MaterialFactory/CMakeLists.txt b/src/modules/MaterialFactory/CMakeLists.txt new file mode 100644 index 000000000..7a6f927da --- /dev/null +++ b/src/modules/MaterialFactory/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/MaterialFactory.F90 +) \ No newline at end of file diff --git a/src/modules/MaterialFactory/src/MaterialFactory.F90 b/src/modules/MaterialFactory/src/MaterialFactory.F90 new file mode 100644 index 000000000..9e4472ddc --- /dev/null +++ b/src/modules/MaterialFactory/src/MaterialFactory.F90 @@ -0,0 +1,110 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 25 Aug 2021 +! summary: This module is a factory modules for the material module + +MODULE MaterialFactory +USE AbstractSolidMechanicsModel_Class, ONLY: AbstractSolidMechanicsModel_ +USE AbstractPoroMechanicsModel_Class, ONLY: AbstractPoroMechanicsModel_ +USE AbstractFluidMechanicsModel_Class, ONLY: AbstractFluidMechanicsModel_ +USE SolidMaterial_Class, ONLY: SolidMaterial_ +USE FluidMaterial_Class, ONLY: FluidMaterial_ +USE PorousMaterial_Class, ONLY: PorousMaterial_ +USE ExceptionHandler_Class, ONLY: e +IMPLICIT NONE +PRIVATE +CHARACTER(*), PARAMETER :: modName = "MaterialFactory" +PUBLIC :: SolidMechanicsModelFactory +PUBLIC :: FluidMechanicsModelFactory +PUBLIC :: PoroMechanicsModelFactory +PUBLIC :: SolidMaterialFactory +PUBLIC :: FluidMaterialFactory +PUBLIC :: PorousMaterialFactory + +!---------------------------------------------------------------------------- +! SolidMechanicsModelFactory +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION SolidMechanicsModelFactory(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(AbstractSolidMechanicsModel_), POINTER :: ans + END FUNCTION SolidMechanicsModelFactory +END INTERFACE + +!---------------------------------------------------------------------------- +! FluidMechanicsModelFactory +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION FluidMechanicsModelFactory(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(AbstractFluidMechanicsModel_), POINTER :: ans + END FUNCTION FluidMechanicsModelFactory +END INTERFACE + +!---------------------------------------------------------------------------- +! PoroMechanicsModelFactory +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION PoroMechanicsModelFactory(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(AbstractPoroMechanicsModel_), POINTER :: ans + END FUNCTION PoroMechanicsModelFactory +END INTERFACE + +!---------------------------------------------------------------------------- +! SolidMaterialFactory +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION SolidMaterialFactory(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(SolidMaterial_), POINTER :: ans + END FUNCTION SolidMaterialFactory +END INTERFACE + +!---------------------------------------------------------------------------- +! FluidMaterialFactory +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION FluidMaterialFactory(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(FluidMaterial_), POINTER :: ans + END FUNCTION FluidMaterialFactory +END INTERFACE + +!---------------------------------------------------------------------------- +! PorousMaterialFactory +!---------------------------------------------------------------------------- + +INTERFACE + MODULE FUNCTION PorousMaterialFactory(name) RESULT(Ans) + CHARACTER(*), INTENT(IN) :: name + CLASS(PorousMaterial_), POINTER :: ans + END FUNCTION PorousMaterialFactory +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE MaterialFactory From c459aa4e972a27f47afca5981a8b7c809c97d4b2 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:39:45 +0900 Subject: [PATCH 083/117] Adding oldLibrary --- .../oldLibrary/Material/Material_Class.f90 | 59 ++++ .../oldLibrary/Material/StdMaterials.f90 | 18 ++ src/modules/oldLibrary/Material/air.inc | 17 ++ .../oldLibrary/Material/airfunctions.inc | 32 ++ src/modules/oldLibrary/Material/ice.inc | 14 + .../oldLibrary/Material/icefunctions.inc | 71 +++++ src/modules/oldLibrary/Material/mineral.inc | 16 + .../oldLibrary/Material/mineralfunctions.inc | 32 ++ .../1-s2.0-S000926149801392X-main.pdf | Bin 0 -> 83695 bytes .../Material/references/Dixon 2007.pdf | Bin 0 -> 119934 bytes .../Material/references/P_Angell_et_al.pdf | Bin 0 -> 681273 bytes .../references/Ramires_et_al_1995.pdf | Bin 0 -> 578010 bytes .../Material/references/la00097a010.pdf | Bin 0 -> 512234 bytes .../oldLibrary/Material/references/water.xlsx | Bin 0 -> 78805 bytes src/modules/oldLibrary/Material/soil.inc | 189 ++++++++++++ .../oldLibrary/Material/soils_define.inc | 55 ++++ src/modules/oldLibrary/Material/water.inc | 59 ++++ .../oldLibrary/Material/waterfunctions.inc | 281 ++++++++++++++++++ .../MaterialProperties/PMDefine.inc | 5 + .../MaterialProperties/SFCCModel_Class.f90 | 130 ++++++++ .../ThermCondModel_Class.f90 | 159 ++++++++++ .../VolHeatCapModel_Class.f90 | 135 +++++++++ 22 files changed, 1272 insertions(+) create mode 100644 src/modules/oldLibrary/Material/Material_Class.f90 create mode 100644 src/modules/oldLibrary/Material/StdMaterials.f90 create mode 100644 src/modules/oldLibrary/Material/air.inc create mode 100644 src/modules/oldLibrary/Material/airfunctions.inc create mode 100644 src/modules/oldLibrary/Material/ice.inc create mode 100644 src/modules/oldLibrary/Material/icefunctions.inc create mode 100644 src/modules/oldLibrary/Material/mineral.inc create mode 100644 src/modules/oldLibrary/Material/mineralfunctions.inc create mode 100644 src/modules/oldLibrary/Material/references/1-s2.0-S000926149801392X-main.pdf create mode 100644 src/modules/oldLibrary/Material/references/Dixon 2007.pdf create mode 100644 src/modules/oldLibrary/Material/references/P_Angell_et_al.pdf create mode 100644 src/modules/oldLibrary/Material/references/Ramires_et_al_1995.pdf create mode 100644 src/modules/oldLibrary/Material/references/la00097a010.pdf create mode 100644 src/modules/oldLibrary/Material/references/water.xlsx create mode 100644 src/modules/oldLibrary/Material/soil.inc create mode 100644 src/modules/oldLibrary/Material/soils_define.inc create mode 100644 src/modules/oldLibrary/Material/water.inc create mode 100644 src/modules/oldLibrary/Material/waterfunctions.inc create mode 100644 src/modules/oldLibrary/MaterialProperties/PMDefine.inc create mode 100644 src/modules/oldLibrary/MaterialProperties/SFCCModel_Class.f90 create mode 100644 src/modules/oldLibrary/MaterialProperties/ThermCondModel_Class.f90 create mode 100644 src/modules/oldLibrary/MaterialProperties/VolHeatCapModel_Class.f90 diff --git a/src/modules/oldLibrary/Material/Material_Class.f90 b/src/modules/oldLibrary/Material/Material_Class.f90 new file mode 100644 index 000000000..1fdcd8e8f --- /dev/null +++ b/src/modules/oldLibrary/Material/Material_Class.f90 @@ -0,0 +1,59 @@ +MODULE Material_Class +USE GlobalData +USE ThermCondModel_Class +USE volHeatCapModel_Class +USE SFCCModel_Class +IMPLICIT NONE + +PRIVATE + +!---------------------------------------------------------------------------- +! Material_ +!---------------------------------------------------------------------------- + +!> authors: Dr. Vikas Sharma +! +! `Material_` type contains materials properties +TYPE :: Material_ + REAL( DFP ) :: thermCond = 0.0_DFP + REAL( DFP ) :: specificHeatCap = 0.0_DFP + REAL( DFP ) :: volHeatCap = 0.0_DFP + REAL( DFP ) :: thermDiffusivity = 0.0_DFP + REAL( DFP ) :: density = 0.0_DFP + REAL( DFP ) :: DynamicViscosity = 0.0_DFP + REAL( DFP ) :: meltTemp = 0.0_DFP + REAL( DFP ) :: boilTemp = 0.0_DFP + REAL( DFP ) :: criticalTemp = 0.0_DFP + REAL( DFP ) :: criticalPressure = 0.0_DFP + REAL( DFP ) :: triplePointPressure = 0.0_DFP + REAL( DFP ) :: triplePointTemp = 0.0_DFP + REAL( DFP ) :: latentHeatMelt = 0.0_DFP + REAL( DFP ) :: latentHeatBoil = 0.0_DFP + + REAL( DFP ) :: volThermCoeff = 0.0_DFP + REAL( DFP ) :: bulkModulus = 0.0_DFP + +END TYPE Material_ + +PUBLIC :: Material_ + +TYPE( Material_ ), PARAMETER, PUBLIC :: TypeMaterial=Material_( ) + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +TYPE :: MatetrialPointer_ + CLASS( Material_ ), POINTER :: Ptr => NULL( ) +END TYPE MatetrialPointer_ + +PUBLIC :: MatetrialPointer_ + +!---------------------------------------------------------------------------- +! Soil_ +!---------------------------------------------------------------------------- + +#include "./soils_define.inc" +#include "./soil.inc" + +END MODULE Material_Class \ No newline at end of file diff --git a/src/modules/oldLibrary/Material/StdMaterials.f90 b/src/modules/oldLibrary/Material/StdMaterials.f90 new file mode 100644 index 000000000..8f941d971 --- /dev/null +++ b/src/modules/oldLibrary/Material/StdMaterials.f90 @@ -0,0 +1,18 @@ +MODULE StdMaterials + USE GlobalData + USE Material_Class + +#include "./water.inc" +#include "./ice.inc" +#include "./air.inc" +#include "./mineral.inc" + + +CONTAINS + +#include "./waterfunctions.inc" +#include "./icefunctions.inc" +#include "./airfunctions.inc" +#include "./mineralfunctions.inc" + +END MODULE StdMaterials \ No newline at end of file diff --git a/src/modules/oldLibrary/Material/air.inc b/src/modules/oldLibrary/Material/air.inc new file mode 100644 index 000000000..9d6c4ef67 --- /dev/null +++ b/src/modules/oldLibrary/Material/air.inc @@ -0,0 +1,17 @@ +TYPE( Material_ ), PARAMETER, PUBLIC :: Air = Material_( & + & thermCond = 0.02514, & + !! W/m/K at 20 degree C + & specificHeatCap = 1007.0_DFP, & + !! J/Kg/K at 20 degree C + & density = 1.204_DFP, & + !! kg/m3 at 20 degree C + & volHeatCap = 1000.0_DFP * 1.177_DFP, & + !! J/m3/K at 20 degree C + & thermDiffusivity = 2.074E-5, & + !! m2/sec at 20 degree C + & DynamicViscosity = 1.825E-5 ) + + +PUBLIC :: ThermCond_Air +PUBLIC :: specificHeatCap_Air +PUBLIC :: volHeatCap_Air diff --git a/src/modules/oldLibrary/Material/airfunctions.inc b/src/modules/oldLibrary/Material/airfunctions.inc new file mode 100644 index 000000000..d4a269bde --- /dev/null +++ b/src/modules/oldLibrary/Material/airfunctions.inc @@ -0,0 +1,32 @@ +!---------------------------------------------------------------------------- +! ThermCond_Air +!---------------------------------------------------------------------------- + +PURE FUNCTION ThermCond_Air( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Air%ThermCond +END FUNCTION ThermCond_Air + +!---------------------------------------------------------------------------- +! SpecificHeatCap_Air +!---------------------------------------------------------------------------- + +PURE FUNCTION SpecificHeatCap_Air( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Air%SpecificHeatCap +END FUNCTION SpecificHeatCap_Air + +!---------------------------------------------------------------------------- +! volHeatCap_Air +!---------------------------------------------------------------------------- + +PURE FUNCTION volHeatCap_Air( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Air%volHeatCap +END FUNCTION volHeatCap_Air diff --git a/src/modules/oldLibrary/Material/ice.inc b/src/modules/oldLibrary/Material/ice.inc new file mode 100644 index 000000000..e82208f11 --- /dev/null +++ b/src/modules/oldLibrary/Material/ice.inc @@ -0,0 +1,14 @@ +TYPE( Material_ ), PARAMETER, PUBLIC :: Ice = Material_( & + & thermCond = 2.30_DFP, & + !! W/m/K at -10 degree C + & specificHeatCap = 2000.0_DFP, & + !! J/Kg/K at -10 degree C + & density = 918.9_DFP, & + !! kg/m3 at -10 degree C + & volHeatCap = 2000.0_DFP * 918.9_DFP, & + !! J/m3/K at -10 degree C + & thermDiffusivity = 2.30_DFP / 2000.0_DFP / 918.9_DFP, & + !! m2/sec at -10 degree C + & latentHeatMelt = 334000.0_DFP, & + !! J/Kg + & meltTemp = 273.15_DFP ) diff --git a/src/modules/oldLibrary/Material/icefunctions.inc b/src/modules/oldLibrary/Material/icefunctions.inc new file mode 100644 index 000000000..6f08d626d --- /dev/null +++ b/src/modules/oldLibrary/Material/icefunctions.inc @@ -0,0 +1,71 @@ + +!---------------------------------------------------------------------------- +! thermCond_ice +!---------------------------------------------------------------------------- + +PURE FUNCTION thermCond_ice( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + IF( PRESENT( Temp ) ) THEN + Ans = -0.0129_DFP * Temp + 5.6716_DFP + ELSE + Ans = Ice%ThermCond + END IF +END FUNCTION thermCond_ice + +!---------------------------------------------------------------------------- +! specificHeatCap_ice +!---------------------------------------------------------------------------- + +PURE FUNCTION specificHeatCap_ice( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + IF( PRESENT( Temp ) ) THEN + Ans = 6.6701_DFP * Temp + 250.54_DFP + ELSE + Ans = Ice%specificHeatCap + END IF + +END FUNCTION specificHeatCap_ice + +!---------------------------------------------------------------------------- +! density_ice +!---------------------------------------------------------------------------- + +PURE FUNCTION density_ice( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + IF( PRESENT( Temp ) ) THEN + Ans = -0.0842_DFP * Temp + 940.42_DFP + ELSE + Ans = Ice%density + END IF + +END FUNCTION density_ice + +!---------------------------------------------------------------------------- +! volHeatCap_ice +!---------------------------------------------------------------------------- + +PURE FUNCTION volHeatCap_ice( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + IF( PRESENT( Temp ) ) THEN + Ans = -12.565_DFP * Temp ** 2 + 11636_DFP * Temp - 356326_DFP + ELSE + Ans = Ice%volHeatCap + END IF + +END FUNCTION volHeatCap_ice + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- diff --git a/src/modules/oldLibrary/Material/mineral.inc b/src/modules/oldLibrary/Material/mineral.inc new file mode 100644 index 000000000..72058e214 --- /dev/null +++ b/src/modules/oldLibrary/Material/mineral.inc @@ -0,0 +1,16 @@ +TYPE( Material_ ), PARAMETER, PUBLIC :: Quartz = Material_( & + & thermCond = 8.8_DFP, & + !! W/m/K at 20 degree C + & specificHeatCap = 733.0_DFP, & + !! J/Kg/K at 20 degree C + & density = 2650.0_DFP, & + !! kg/m3 at 20 degree C + & volHeatCap = 2650.0_DFP * 733.0_DFP, & + !! J/m3/K at 20 degree C + & thermDiffusivity = 8.8_DFP/733.0_DFP/2650.0_DFP & + !! m2/sec at 20 degree C + & ) + + PUBLIC :: ThermCond_Quartz + PUBLIC :: SpecificHeatCap_Quartz + PUBLIC :: volHeatCap_Quartz \ No newline at end of file diff --git a/src/modules/oldLibrary/Material/mineralfunctions.inc b/src/modules/oldLibrary/Material/mineralfunctions.inc new file mode 100644 index 000000000..16ecdee00 --- /dev/null +++ b/src/modules/oldLibrary/Material/mineralfunctions.inc @@ -0,0 +1,32 @@ +!---------------------------------------------------------------------------- +! ThermCond_Quartz +!---------------------------------------------------------------------------- + +PURE FUNCTION ThermCond_Quartz( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Quartz%ThermCond +END FUNCTION ThermCond_Quartz + +!---------------------------------------------------------------------------- +! SpecificHeatCap_Quartz +!---------------------------------------------------------------------------- + +PURE FUNCTION SpecificHeatCap_Quartz( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Quartz%SpecificHeatCap +END FUNCTION SpecificHeatCap_Quartz + +!---------------------------------------------------------------------------- +! volHeatCap_Quartz +!---------------------------------------------------------------------------- + +PURE FUNCTION volHeatCap_Quartz( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Quartz%volHeatCap +END FUNCTION volHeatCap_Quartz diff --git a/src/modules/oldLibrary/Material/references/1-s2.0-S000926149801392X-main.pdf b/src/modules/oldLibrary/Material/references/1-s2.0-S000926149801392X-main.pdf new file mode 100644 index 0000000000000000000000000000000000000000..176ddbc493fb75fe8aa25946a92a0eca012895f2 GIT binary patch literal 83695 zcmc$`c_38Z|398Ewi#QpjWm`@)>)V_D8@+E655n9wrpchyWNm2q<2+ zqD3a8wAd9P;(qTPNuk&4_5S?+_^C7Z+;h))p6A&f&*hwZS6LVss$f*Hh*j_2KW#?v zV$mox%FEsjp`(LBsF}HXI#GOG4?8)cFyQTG6c!6!j8MB!78Hg>dq8gear_&wmGfotzOMhZ<-U0{!z3gGaGq zC{G0MOcDmCPFRpePzM_Z{r#4Yh{w%O!(uTS3(|1tg=v~-;{1F#yoUOMG~z;f>ID3P zvKnaY!ZdZv0-iNApaJ@`9U7Y8Fw9HCt7|Oi7XoHsdkHwA=KQh*b4CU{Uq? zynty7`UL|{=LPg|1k3_@>Uhljal@$N7tA$`hWdj31Jf4PfyaT1<A=IouBtj9;2sL9*XD<{qTTqrD$XI%L`J=GloM7Eq_&NnZ zsDlSlN6pw^myWYD7VU_`5s3~IiZjm1(cT&BJDhi`hU-13*r~T&!6J! z&w?N{V%4e*n+<1>48f}T7i3x=@^(V0ktzNZ53hY72NsllPJSq;MJ(<%dpmiO9Q<9q zJV6iz(G*HmGj#PgLJ>7JSzrnkF!yoL|F`& z3X<{gck%_V9u$8k11AR-5i=*xef};e2y(!xAQ<-Z_jRIB5xhpn9qjDvobBw|svcH9 zd>C|!6wJn^=aHho{#cTe_T=;RmF|&xSY;Ep>_$l~?M* zShL^ZtT}$v?(%0T*})}62`59I9hGEnDTTw$zUr+{SXw)TLu)bg9M7&ctd_Q0vgFpZ zY%U}@escX&hOn9g^*Olke+d>=cg`CKs5e=o;Ope+KQ|1PPJUkdeI3A&!GddsH8Nx` zPk%6vA2=@RGjmCOrq940hH_}kWYhrXHFO6qQ}BYH89_X_$iO>D7P3YRH9OqqPL8e= zeXoNcQAn_AfI<>NASff**UNkM2?hr~15ra$eP#|=dijGx2p0HVZn8N2)jSJdF9$0p ze~_>mD8j)x;B?R*rDjY8+pEu_ZwR&r1xj%>LktR($Pj;OhFBDChE+8~914POR;oG* zJDaKj3iY3QR=hhKv4xM1W+C&#W<413^&OZ|~1q zb5JUzrEH>5!Np^!4o3AUeom}xYSyk)CqETqa89BN)=n6MBI5Yi$)xvo?9Yrp$|a@51Sl0N z`R@ymD;DA@?p{{X)6uvAV87Z}e+;MQw(*NY>V?`5KN^TqsPp63mW^dBkTtXEDmY(mR%?xiajnZdpU%$_T4>2m^zR36iFj7btoy<28AEnp;WS` z{+lTKzV8|i?_VgEz{l(Sjy`rz>p9ju(5NQ1%%Z2}{?e{geNmAl&PK!Z+q;hFV%+nQ z;y$sGsNGq-VnG+MiWGUZs$|AUvSS+ZpfbHGG_}Rzgrm!J)1yuHP9H}G8qS@IL@DZ3#6Nf`# zupkCPYApuJg1~~Lp)gYv6v`+~4ealP(4btx{Px4*m6Zm@G>Bk>q1vIUpzE(V_yCHt z$U=?$$A%()V|-p`{Kgx^CB)!jng4;pJc56_U7P}|zF(F8Y!4bmL_+}e=Rd@sxBu-9 z52E=@qo7KD<3SS~oW&ZtSQ-%=dOQXkXE6NFTtK4)$(jwGpfcd?UJ{M3XvusKzC-hVWoQ_bH9+Z84D9Db4D%YQplPVZ> zlnQI&X`pc^O;DqT+6HBqf&71O$qfFJJokC9gsYmBzY}#EIF~^(JASgG0X7e04_x7p zbX8FErhuA*FU0BEnYutN%L#`97aJtR{^*3?6f=a{f09v<$^5?{%HQVqViRYvG=v6W z@g=rc=D9Rz4$cO|Yy`T3w#gsphJj{0>xcCK3mQ0cR9G=+P5ibJ=AO=jxPNTv3<1yv znooU>+)QOGY=n?&7SmYCzuny2Vj^Zi(p9zFbS$2Y9+Kh)IrGs-9udpu?7W59za(O&@TYxnZ3>s zfD(QZfeNXE2*|p!gydqZ&j^G604=8a7Jq>jjm4nlr^5NW<_9JHM`*!=y6f-Iq5(P{ z5Nfl~05e3wy5U1R0vSV5Q~WCQ1)R>^HfC+^ zl5D!iJI6hJ z(xmFmyHHVNiOhKu@RvLVXP2w9vlA#HAX^eL^3*nMH3Q8*H6v>f22g5dhM+D6`U5OM zIY&UL8Eh~EBcQELa&!et`MLT*Q|-6u4$i;1q5f&RW5H?skCq495{{)y*x1;XK@w2k zSPAlzI9eT|Vl*&NGJ0HK$vBd2Tx#j~3ifd^j!6kP`xQ9HxD;G8dh*sp(!^2DF$ux3 z6#`?jLg`}{g_p3iu}QC0-RR`$C`ihB?enF0yMP`BoT|oeRj{HLxK`LMqZ111|+WazAxR zeAQE2@7QI@vAbV7-ZP{_E^&gz#_HFwU-^z*{$j@%x7K8>FdR8%Zce3R1hrzW- ziJ%-6%5>n5N#SQ78!~C9H^t}0*L~c5bHeqJsq?1GZ&Y3p+&jYqzZ+YL)}7Pw8Pqx+ zpOW>pAuHYENn!QNubXZ*y?!x#L*?>=ymIGVk45gCe$<8(GwrY6Vbl7Gn7h-LQV~A- zWW}=k^4mA>(L8dfCb?(N_p=hzW6x^0)$PLW`&3nS`P9iHhc(kTUBo*?KfnKmhiZGN z&DPd;Ykl04*Iy9`M16tzPA6ga``b6!pk5K2UKR%4{PulH<6+{2Uz=OUG&WJMH0R~JnYbS;;{efMWo?n} zoAy`q)kVSIbp<}{$trzwMC|KO-_+|WI-j83k{*GkyhUaYA^vX;2?+k@ zls)L~Z`PwG=+uI&5J(0?vR)H3zzCpI3X;n+vVTS+n-7gR0P2y#d3trkzTZ}zgP83zk$qLmO=t4C19A@{C$iH6%7C!u)ZmgNeWQLR8b_fL}zr81)t&noK+G^>TIFRo01 zbN6@k$;N@=>*cBD?d0p~<@kpJ#S)>Ge@azoel5~ekmBD~D`bVv8Oby5LrX6z#q&?X ze=&UjfiR?o&L^zz<>B}z-M`q9i;c~UmOE!q6IlDNi;m6$gBk=D6|5!;I3UQG@l5|= zQJZcySK8p==M(_yD^}i44z3gr3sHx|G$dzd7buEd6rKK?`cm?3;@bLAw+R5QGqZ!Y=`YrP(l-6Tx!nXo8Rm1tK29 z$`5((p@2byy~)bVa?(MLIxs*(^eaH<%CfE?OY3KVygN`FVh^%wp(`su=Gv^u2JL)9 zaqxBfY|qa*K0BV!73yG?gA)rnmRLa(4{m?pSw&c* zOaM(mb^J`w0BtL%ggTf3g9ab`oDyI%0t5d15q=3&O|S$JGz6d?)c^+>su$cKW>JFN zrjSDh3J8{u58TxKeNdtJ&sv~a^~+T`JD3nr7GZD_vRpfOkP;+ZXNf?w84CYFg8Xfr z&zB=Jn>@dpEa2GBfGgD2*+U*I&0)TFZDzB5-nJyG?4R3`!F-Gln5f_eKTatUIV2;P z!Y_!}D9e^o<*6zOuVO#QxG#^wTp;OxH7?{eAcRJv6D(dL1tQ~8QjLn=Iw9j@xrBK{ z5}1T!lMn;hwAeV#&{Ocn;_&qWSP6uK5T>}xTUETt(PCIrQQ8_48e<<4#jsS7Kvdg@ zVv?(Twa#wZctMllp^?Y$rJvMoamw&QldA(|f4ZbfC8G1XK1#t}wbZd}Ob&6I^R+lhOKPeIZdOy;p1{U_@sf*v6Jv=n4tBp0j zZ*5?7AH6y|^xZfbyJ`KP&>4}9TzH=hrc!|Th~bLFY}#Z{jFo|OVh+Rhx}a}$VrOCC z1_yZwvo)p}Z|p_zslk<)IJs+|KWNjr-w@*Nz8}Un@cS7~>L_O3KE)FHunCRBk3JufuF6l~KulJ8+UHl82dirL6-H7%Y^dKmD=E+JV}1m1X(%KtI!U>E)q+hu22 z2gK1)kzO6XwB>$eY^=AQdiWB{rtgs&`toC& zNlQ26KK~r$`#4e{qlJ^#O)^G#>vG;T(${k$l&o6qLk@Vbr%t84<#0E$0|A>WRie>i3~JxB~y3XI~$NMUL&FXVN~3Djoc|>XX>=F0oao)6ze$RnYv{rN9yL zTuh1My66qjQ*0Z2h}^32A2-2Z)%q|R3bxwN@bn|dg|_ET$B^d-fsjWB@aR3ShdKww zTx-j3d)iIsPCj1$Y$CoP?^e$^g49%g4xS%)cj{w#>hz`VFNsvKSG8w0?~7B2G8sAZ za`OY=tM=q+t^-~J{@xc?myefFG0ZF1IyPJ@4=eATdO0P{5q`L1e>qo>z%(K)h>K0e z;>UrUH?Z8nfQ}DkwSh&P`u95W%KL)_4VX)1jNWXD&-UpVD`J+fY?(8x?X&vd#C#ea zQod5pva1IzbK@4;)!=+sbS{JQ;%}Nd5qvghSF`5xoM8>h>EE|yXO*)#b#5*ONmAC` z9}!4=LRuH=31o;Ppp>~%e~rxw=U>!VIU!OrI|mT0U!(}2vh`<8vz0(92dm_tbmnOM zQV+q5vm~HGe=z;4qF)h~0tnIkl`_{7h#N>1oFlO)H^1$Gu*yO$f{M(xd_FgjCN|q@ zh&=Qh0qHUjyHKHDZJkvS|I771sgW%Hes<)1qCW}DHGh7Fx%-7=AeR3V2XjOg#{Pi- z)SpnFv1rJ{$6==;ENv@pH8eZczc8c7~4^?yhDu# z1A!^+hVue2mHZ#U6muz5aj7qoo&974AA6X5m?Aq)PA-NzeS*JiP$1|ab>edIai1@= z!6(SG<-4X7gb~MI9~vLZx)jOZAC2ITKaNP;?0nDX<4FC5JvaLM9z38@pC0T;_%wO5 zW2$e>*wN~(y6e$FLEmxa`4{`g3d>zHb=T)iwSU9KX-pK+K942nI%Nh`wUk9pDL8y^ zzc@h;cs6#q|JXVYU%s=zuy2wil`9kiQNu%P|Intuc^<3h1-VxVMB@po~eQv5+p8T1aQZ1#lC+$}EfLF;Kw z;A=p5`rDqEfg0;fz@K7&q34Qq0PTNs=Rg~Se-{#v+VRUp0G-{Lg)Zp&dtgD>yfjwc zpWq9@8iZslA@O^`-{Z6R$TImLOau$e5{8~Z_bdZ{HW9i)0m5ad5OjqO^B#U}c7Gz|6DG4JeI85G(|xK>;EJalo2mP=;BA{0Cf|&GJuIRzE^NP?#B0 zsJfXV5SKH&Lf5$*bFrCx^LUtf%tB=r(V0xYlbTEUMPR1T>;vd-ewcl>*pY=PMf zv-h)Ch@<}^9{#pi=L-f1T;>UeS(haEF2J0b|C_V!m$X>K%%AZZK>M7tr;meqxn&bw z7`~b!67{rY=NfomlF{(h%^?qZJh1e~f?^S$rmi^D?%#!9`J|V|C(3Y5au!f z+ni)Mp(8^M{ZxGXeR0=K{<}NQm#Cb)zAB>Pf#gl%rn|ZF+zrh5fry52=b_Ba^4l2L zExk@FYdg>G7AN>RoEG87#+Ixy9X^?v+|YD!Shm(vYM{GrnF!-cL}PTH;<|(wQS1r! zP!sh#seWj@VWy(tv%2?Z8|jrwQFLiMn~QTMtRl*-wOoyP5Wun@QN+tO=1Uf5^PTNe zzxG63jlZD6#Z6q_%chM&L)Q@~Fi|sI!73kR*{Bx0)apd}QzKcq*#Sr~2h?f3EfSXG zglfW_EorL71>|)K*opwh)%dvnt(D@ca-q`%S-SV*{oDHNKbA7RY|r@YC952;iHnCH zR^;3)*pA_MRp{Rj^X0a{sdeu+8;lT%s6EisScr3s>t&Xe?BY@69;Bx#w8q5mfBS~` z3}+F0>j|YMgx%)kW~NnM2=>F7+IA)+NV+9T^{DV$anqU3icklr=w{XV96?pQqbdC(h@awF_4j ztL!}I*>WDeYilh;u*f)0dSY>~8%BbUM&H6#D8Lgzr+g8LwP@j88yaOnIV35G5nK*` zcs1%FN%f4W0XwO<*c*E;9#+|zY;jXmB^oB%X_W7*E*Z_U`u$Z#yQ9|G2HMF(#g?`q zOVjd>8{FEVDjsiG$>w3;OuV?9JNOn4EE*>n&&h=|zWBx!Cu!y^>GZ$_FCqnBBX|9Q zdobZ#&MUdADYZ1@n}$d$nY0=|I-C=>%s9Wskq&>vMGjQ9aMF=NoU19YhpAj`@i@ZA z8ExgB^4@2J5?3?sg+FUf8_u$iMKdn0eax=9Or=^PmPZxa&f*a(<{F_>y8ineo8!9p`oFOa$owYLWY6wHO{<7M-kq{kqKm$Ir;35yEP86 z`r`37OaHQ=KF-fcjqXDwT&8GIu)f$`YPEZR?eOU}W-9Q!!8Q4YoKw z*rOia996SUck{crBU-VRaoRgy_4yKG5@9`cqQodSZ&@=SxWzb_+H6y3;BJyTYWDfhKC>)$P z{_z@L2KORMbJnc}ozVWZG#5KHvdGe$c`xJ-fd?(klnjwwB0}+oR%<^udE%lsq>?fo zS~#FDT-!o=m{RFMyzt&(OHN9=1Lo2uOHAg$Pe|m3SR7mI?siY&xlL=V))rSg#XXX* zb`|fk@HqMS(W({^VFWjJ^Cst$S3ly>$Y^*q{buav{pd>w+@Ygp6jAN-h}F0ad$b%P zT3m!MvCnI$7^xGhClwkgDuidMNle>17mP%-%*cJ02eBH0a05;I@^i@@imJ3%A66_~!71?UI8MJa zXFLuI>%?94wr|Y$lsij6I4GqY&u&oM0F%!`*YuG>PDX22bf&me#ic5?#Ky^;Z7rj@ z-jXhcXFXUQM{{Eg+)~N89X(uL;}-=@!MAu-SJ_x?L{FF2ifhKQdGGmeE4U#m88*J? zcvHI?qA@AYq?iBMXV0owBYSnxCmu$iWBjU#iD+(=B=0+Zc7@l{B+7XuE?KLjU2uN# z?jFgkXW=*2rRN@r)8iDb`L-?>BfK8J*cbpcx$Ez)u8GL+>9rsXDTOO)M3F^BY3648Y+q%yqBYmcIi}p+9#W~5 zU7L3+R)TT0q%cwTdBoxP#w~G&tFqqT(#yTUKjhutvixgP!JT}%G~>lv3wtE4Gi;T` z!&7pmR@PJ}%a%gwot8JaqR^*@UKSO2?JjtJq&mhxP0|Kyfb+P?xlT;J45<^ZxYE&q zCxbD%(Lv#JUZhO8vZVIYB^IJuGHG&L@A+Hb6`HFkX+G84k2DJBk13PSxxU3#Rw|=L zZ%{Y$<*v*)Tk99C;`tS4y(Ku7ml%mCzObD#Z=YCw{MN&)x0JxGA&;hO@>_=qw>7R- zKe^L(KgwC6Pb{Y}ICznDHS6Nj1mCOuwXPO(J1nxUptAEs9xu0jg;72;@|-kC*nHUC*!#uRszmRm&h%2 zz@4wJmP_Z$;QP`IVEBZzocev=T&9E-#Kpa zIN0Q|!VyM}O7pLx5G9RZCo$ozs+y7;s;zt&yIr-69PMuRzr0)eEG~kcm=Nru*$Ma1 zl#0MC5q&VX~UblYA{_9S2fM%1t(7++wN zaJT439>EU6u`X}Y!tXbo?DwLRX=}}l+l9U_8IM@ zVK}I4LNigol`D2QAiZ@`PAOi@VJ@*2;^ZQ5NQKx2-0D0~bi5sZ{|)-+1EgKPcde-v zyNbpp&fFTDM7PYX)!L6-+<4Dzxv#NZv%K|^a~$UIS+^$L)cr^?HC~8R z61O{@(#!Ccy5+9fdA{wQ`{B%@p4!mP;*7ZbuLC&;tMUBV$3z$}2IzjLxL-Sa=SE5f z96A?umD~o9 z(KU=tv%!hSbHe0q=DZS(MQq^m;{kU-6X1rSVLr(Hh{?B2pC!UY!_9% z)+`jZ|Z%t+C6<#4^ z8aeu4mm^9d-cT^HO8AlRd9w&ES7KV-p#%sFu3qyK6OWC6E%SNMO2H!=?ur*bbUC!F3EP*n!C6`CAV=rDy7N4YQtlRVWIF( zY6*z?FVQ$9DyrR3 z|1RlzrQ5Z%Nb6dLn;48Y!z~l0WM7qM;AUo0NK*=3u{)gad{4=(n#%lg%{$9@ki~0T zYFEYfEKhiz7cFjsgjwe_;rUOKAJiCjo=U;$G`QFNXr;uwt20--b@*g0n&Uy|mJqTV zGnVYIQZdik+vZ*k?&9GwlaRX)s@n$=ELxZZX2~IZJw3jwCUfdrASb(BB@sTZxWT;b zWU+`M=OzVc>pP-fh6`aT`I=~E8`~cVxAFdRpYi;&ru=*Hc0&8hlf`j1YnOf_!WFr@ zuf1*=)qD3LB=bl0#_tcik{UAKx=3k1p<}gc(Q$B2r7T-91Sfn0&o1}g*5WM1T_{KK zZP&090E)F}{@jRVy#f2b`6WTu>OVLp7kR1h*U1t{EB$pM1aj=L+-Gw?zaOrgOZ{!n zX8tKt)L?qTp71FTamkOzw8lmwqcdFJYb z{CjhE2LQS4If;Cr!6@wgy^O9Jv zB0>EyKOLg_vnOU=S%S(!UksQzWAm$97b`d0cBoaqUWS4i47yc+`<->v{quF6ck$26 z5V^mFInEHQZh=|^z27sJ4)yGx^!|1?j|s>#`X5}0=9>-v@@5at8k*C8o<9W-QO$QK zg53VcohI<)*?-(=VjaN$cHr4x4&d{H2k^)LegNMcSoeMV@YCy=9m5=DVqb#P#CA`I zZH)?vNPMP}mGhifo|314TbF7;lG|xj(b&|aSAkijyLPKgabB^!M$wLq6*x6wc?POn zAy-~w!)8(iX3a*n%&R-DDimlIWWW`oYbiUbDh8bF>@4%Z&n`G8Q0$x?9do)?s9$8T(d&U`si_f(~>L#ga>RQrV@m$p6KD>mL$++Mr!!S21sHcfm>A2cc1 z$N02aWuiVodW6{%*G0Kh+)Zk_wC+iNM8v&&tB9OEwa8WDk~gMZE)97c>F~kd<1_;f zX^#2!f4E$p6uEEMT6#|~_&Rlw`E{R#yHTw1T?G0T-Hn=g6YAGtVs+Nx;$LS_STAuc z{-PH6{wM1kI~qg`0*E^cHlzM!QZBwF#X2MK>-|p<1%BU>@^hlPI(T`2M~!{%#+6E;6JEAS-btY*dfP{hBx^jKx*X;w>VOFQdCd{N@uyy1ElDc)-p zB}4STqN_-viV`XMofiXycxj@KI540MM3ewM0K>`2ZfNmn1Z~*ovgsNrUVfNWVp_W+ zvHru-utR5AK6L$OQHivgRTyttA)|JJgspCLeI_?dtEA_Ze%ywQYeXg^>Mfa zZBf1KX-uUyB)&r8908oRE#=I46-u>FsMi&a1`V z7q7dznGJIC_KIR+Yq5^9xh$nAJTh=1>&l^h>-G)pRiU9VEx z%=hq+7GjxXqG(io^H~X$|I!5c6zE3PZb(#wo%nC1uIocEP@t``F2iuU+1)+m}kY#T#L@7HMmd6a8cKgH1lK zMU480Qm?N}wo*gOt`jzArSeHp`%D;HDh-qxKn*eXxMupNt^g~)e8|LO#j^)1BorShaw#ejs*+<1t@biRDM{EG$j6x-2Yc7~u;!&^7J@d^OpUbzA{79GALMFd7$U^@&#~<~ybsj49^SUfEaMWq3yTVmVoE=X$hC039Pglb z`Vp)`ua1a#@8>C6LDAo#rQTn8?dH7(lVSrGA+4RE2c%SMVlq|64ZozM;ap_WzeXsYq5n~p*RXm=YXE$6L zeW9-_;?`R`$t(peVM&ELNkNJ1443NMn2=!mjweG&cMT#cg1y928t%75W~$$pRp5~| z@{gk(KWnizl@jInh_?K;p~!ZHbqDsmtlQydtMG+-G@Z5$Wr5sDit~R|P|xjI*Rubs z#ej`jeaNn?LW_M)HU)WG9ACXuxh%pbEDV#4j2G%!k<_XWaFXMnG-$*ED3iu8ND3~@|{EC8an1b)%I8*j}`2X?l2G;NC5_wt)JgQnE8^QzN^2Vg_AFMkki}C z6Z%F2n3)VpMDTSGiUati9Ru*)5C^A?zLZ1Y>#j3jo5JEi1L2ngflM~Gwl<_3{CV~p zdUFW+HkAd%m+Hs*LXj!>*#{QQ{ZvoC85Tg#`R~s2;b3RpDj)8yjRyV>7^LITkB1z2 zLe3K-WgeqHN}c@}RzW`NM=`9F=dZY-3(Wle$g`43^=CTPQMfK}QwPYLZnQz41~76{)x6GNOJ~2wm!uLyjj}Xoy;;>~T~^L?kOn zrt9l5xM}xFN$iSxtp*|aHHj<4Vyjt|Kdfl<8%_?lmJoIq61Y(Dbs2py~4?Ktbby zX5bqXKc?I7KV3e3r5TvqR0MR7ZJxB%%?7$BfsyGez^!9J1%qQi_f*hS5a8Z=Owdvr z`1V82LJ{~8dL@5?ryMYl(3rk5xkoUl(W?uI4{CNDSvEC&a=N_#u-7CovFVC&IdEf2 z7ijLtp0uR~0>I`Gkoe#rFkMzWxhER{Zr^wTOaR+Q%NedGfI}R6n{Nk6#sI*p>D28& z!MDJ2u-+*pfZ@vj3U~!fPEU1VA5V1j0zKt`YYT2Pc==go_ZBn4y-bYQG4GGe72qJy&cqr zGxk@hf;;uVbmsQn>|;QA(4MAa*+2&Xd>aLuw*J-RUa%$E1;C{7Xn99(f6%M^(rloe zY)d4sbO%OrC-)Ba2Z50!uL5Att5LDZNzbT znoBDw^9ijwHOWuB43H(5x`M6<8%hL$bCKEWZW9lG!*N~%RebX?%PXke= zK_`>;>gW>--07{sO)3>Por}dKoD<%Iy)yInAvs$$=BCp!*h!iE-D28`OIIbsk?@c( z(WV1Z@sTv5uAge{G-3S^eFP(fInp&zc-Fgj?@gp?tz?42$bApEqKy@K7){Y9UC*>cQvicmhIyvmk z8BQ;%vMx8FoNMe=)3GvOzxfFAM*rlUa-Oll(KFpzz}VO{^LEgFf$sA1fm87(>CRGD zYu-r(1(mJbY%ePZ*k=#)0$j}%9dQ}!4(j$BNqHR8764FrPT$$XJf_caUeEUBTTP$- z%5}}$7hYdi(3+qV+VhpG{$)^xu9KTpGLd|#Mw%gQ{vs$qAT`*Y5WP2s+KXUQ-x`Bp(~X3dW1cJNy(t~Ep(1T@t}9`^DS-|3ONO6^dDKYJFZy15 zf13F2+3VnaUo8>A6O06Wu`XEeM*Ea4?c0L0`QG%U@er;#bAU;9!B2Vu-WrGgSovTj z-w<%Aak(#7sOYiM0)Ye_z3fxyhK(`T*87wXCV2QtG?fbpmAi_-?tTHlh1EvAQw~ma zXr;LWQ~5FLT2pr8eP>N-GsfZp~BfUnB6cr{&-P3HrmTfU~1j= zsTUoLa^MSEe_o;&XR}&N^^PtvN_vvQZGQMf>@zBdk z_oJhnjQ3_6}9jc_OCid@yb>p|T=ee2b8vT@D2%l6M@|7$$S)eub$* zj>b79cyoc>Yvt>~DU1|iONNH2kqds~?3w^-jm>oOqeBPE9P;*-GgoMa zEN_4Ha5+2Ow0>vH4(SSZfFX_8nxL~Xa3$a1JT`3Qz)!mQOc-sWED zR)3L}7Y}H!h0#mdcRx(?-qQ7unhgkzbpV}{K>H{#!Mx|a{W4<<0AxTDbsCr+0suMy zpwi!*0mgNKG=?&Pclh%qp=S@iuHXA3wAr^oZ%DPE@5f#_(=GvK3{bT(Goc-`csmCvZT7j|Y@>}jqASin(t78%XT6=-L`=?tcr*7{B0?MbT z`+?R$pa2+j&;I723V_g@^XgSUt#T5eM0^7f`vE$qkOVn7^F07x>zpL}S=_Qo3~|qO zIqhP8XmC~j={Mkr&HjC=V0BQ*&~rSY>S)(d&cLoq@p@nbp=v=;Bm-RhTDyyOnG$Zfl( znf$hI#cQkX9C|H{PFkhx{i?iC{v<6lWygU-R~l*)SK!;>+NR!==LZS}S9PW&3)@ZY zIHH|_MpBt)_|L%C8}|2d3vWj#%PuPlD7u@^9)N72GI;{psJ$u1w%5ZqtlwDCHdet- zEiIvZ|FWCV|Ac&pgGaVQg>H-rHKqp^nJuFhGMUCG1B@a4MQf0;$^(K8&n{S3TWg1b z0=0ZLep9vD4b}&xHh)_(vy4RupAT1}30RJwSI`ZlfPL z*7ihgvj>Xl$?Q){k`HE53;NrRUR3KJ3EjqIX7*<0e&@xx7E@_$MP4J~)S@(CMU@)U z*wTc4WK1A^$ZdcLCzOp1APV0E^iRm#HRwclq@ARe4vZC1#=I$oD+=4YRcM{LrbmWM zkL)*+zu*-VIlc0=_&HwNoT-5cN+I2S`s4_6>kC?SulI+NZG8!y%?H-($a&OO(nCkk z5ZSn8mGVUImA5BID0)C|WXEvjgf}(vK;cvvHOjnrd&QddYEMeMqK#?OW2Lqo{W*== zK_iS+;&!FFyWs0yPRTFh2O{^3(gi#_!(@WjP>Y&q%7nul8<`cmkrULOBzUN8Ii-J^ z9<+KLP5(G^^atKWtjWvTaFQ}X_cC}KN;+}-bSH4YtGh(D;#5%gvU53Gl-RvaPkM%O zZbMEKH>D(Qj(k;7TH0SW>0Pn9t=y=^GB|>RJ|fDjT171%H04%86!p_qe&^iAEa^WP zz#VF~deDo^A+F%n8gSCkdpl_nM)vGxL;He;9zPT2$_Xke4CNts2_}&&`Kb4;lMsa+ zeNkH65l4=o+Py~G9-LtphQ*rMjt(T5m)3fp;#kf}ElYgpOH_h&yp$GJ5gn&~($!^t zhf8*$_6d|z8%gM~Vq^IvYo^H6H6(P$EB@N^bk`^2)ZXllbF|D@c#0P@povGC1Ad?~ zEnzG5K1sO8M1qf+pC8i6A=>_0bH{;WtC>X?U@fSM;Y+3MJWFM+jgAN#$rn)N1xe54 z#Ru=isT5Qcew!+KF3YR2lRvoTXo_4%$<2pvL;5F7gzpq_>%S9P%5`{3$t#DsVw!n0 zgkzLj+_5wCKu5qA9z=XbVu&doHnMXput*( z8lp5MNzj;@CzmFqe91)!ev@fjNcY&))Am&%sSp|2-!ViIG9*yix#jt`y}pMcTc?DS z4A7|w*;7UNq1)&l<%qJC6p{X7RES7$VupOwp$lU6DN$M-sc2OE39f-crfcac&vDeL zLS&dgf9bAISrtN~vcmEk(<|Y!sGY*@76#%sneK&y6FHM*g>M!%J%t5_xw^>i z2oo56%^PETOMcj%e(y535{&LaIH2s^v5hIqp^9)7GY^wJX;awZYD(LoSDnPYd@xXg z>r=_{ZGtCqOvD4|9`UNk!qH(1?@D7bTuMHFlN^;MLgtRrJ1n>{j7=#hCVMBW$gLuj z(~e1vrc-;`dEr|NWrXBzJ_MIFkKng_p-t;Jgb?AY2P*=T62=@7cKZ>*)2rf|_zmgI zW4m$^VH`>np^3CmE@~`_l0u4fK^-SWE-!V7q!o_D_`C2t(ToZW6ZG&z-rqK|fw7g6 zc0UwR*bKMul;IF|^se(7I+t>}$(Eg?8^*ig;oC=8!tY?q|1wT9(tM z$Q=qh<5?V9*h6+sdviP`O_=cpr`~bc;+1g#9Q{T(5shvs>~lwS>&v(qQ`1h#IuyP% z@|CcliwI|m`|`xE2d8Mysnr!UtX{;Ua1w^hbkw1Qr6rI!l3M(eqqVqq1&SAvRhM$F z@}`Hub$4P~?50oCQ9nZE((3hPoD&te0$$;0NK1Nq(`%`XmlvQ?#7xDvp$-!qx$AyfB-fvD69=ya|V{DLpW0 zn*`zn$8vvR5}CjMPEJcxny@ulud|ysly@JcaH<7kjIzyXhwtw%I@|+S5X#;$`_ zORw^%TP-VR3}>YyP*c~nkoBXS6H??weT^bq$!(PXkH1Icr`jOoQ}*10Y&-|M8`0*@HEdc zLX*7iVQ{!<$ZgC{S#h=7h{Cg^8a@y7XfuyCg(C^fS=effig+w?`o77@>qDefW(l2< zMN#Pj=_E|y9f{-pqn*@Bj^!v*3p%2x7m-$0rZlh&&trm=OGFtkZw9QSsYIbeISRZy zLm!ZqN<2K1W9e~k1;0@MJ;JV|kRjy6Z}CA-udKaV*i-1N`naPm z!QDg}uD193jc{RO7+oNR>EC(Zf*KVSF5ErFC#Y8@9_Hbnp2y?zLuvnY>oT&w{~g-5 z!q<;^ayrh3z|Bx++VXQkVB=U0e*PCqa9U*O1Sl_lSQ>>R;JS$1${f$nXSn-{ID~}P zx38dZknai6@AHe79=I;|ZK6BK2$UeLw@Y{mJ2YUAb@)TJX6FknZ!)Yv7CpMN#)ofJ zR#KC(Y1k`cxfE49DRk?mH#?}^!tBcED%8!XN1Q3498u`bc9V*C%W1X+2~ppchm+L+ z5~x5S^UaQwP|7*G^`5e{Cf(BI;R0K0n$us}Xkbol zHQw85EH5NFyspSdh@W3Qkh$Dz%4*;$iis$`(-!HO5|z4)dOdfKph@`h3=e#}&{CyF z+2w6_CXCIx#PomYBWU#Hg)Ni^mK@+nYIOTw0rwO_T6tBTi5y+Wp9otPF%m|hNlww2 zB#x8RrcHiKV|g?0lWlQ=?`aoTGef&NN0LLi_lCl?-2={2J2`{{nk*RmZro90?uSXg zY_)#d(ZsRrhagsrPO*)m^vMgFFpU)glSX0!`twuX*mkb4*^C zdfy1u-jif~iIPW7GwefmGu&dU+dLmXM_s;~i}tiF`(&jSCT1*Ifuvds!M%^96^!JITD&SzwsKL-N|IniTkE%7qxAet-S8DT9fj?bZrR7Mqgtz{Z&26_nTR4% zV){m-uni@~D3akwQgBN;BkvwDQT7Ee_#`9C|PHg*-ge z>`UOKP?Y{M5A8}BMO1MYo)keT0nb_;KE5v64HWnt`5-5{*Vq3d##HcoZh2TRx(IkV*|wsa({mQ>np!s3 z@N3R)(ZjQFWb5__GImE{xXs5wmw=P=nUyC-p8i@(LhxA;`+AFaM2ik5aEmb_+3`&! z5q5uEH57r~X|ChBezpEgGSVFs;@u^zn)%Udf!)MZIQPo1LzYNaPbL2@nj5H5j=4@4 z7K%{cAnFh}*5Mhpz~Z|I!9RaPo5ZvNMN*tM9 z%eUaRd4vv9;=U3VBUw>CbhU#OaQ9;QnZHv5rsfeT4Fvx4(Cps%x-PXWw|z$ zl8TzS9h$g?44VlZ)AdD!nS>X#ed`AgD3@j!-T|GU^CK=*PDq#pDE~D-GXYojIFi95 zL@F={Yk5msn>Kw*Kn%ov3|w*zmlN1r=Di4;TYwC>A-ZJ6UBUGZChXXjq_C;wYXNNhZ&zq*N5B3x#myg|~^AqtqxxI)T zW*zzrj?THdo}Z#GM|mzu6^6ab35I5hM}wHpqCnVbJ_7nm_D<+$^8eCf`oBe(jvcS% z{_Us?u|7MdeA({R=z9WgerD;SNx%t0%p_3aCN9d)hHfvMf_`NjDuv7+vs0m zHE}fu#tSIx!;nR-kO345OR;4Zc0P^7T1wFQqP2xEWHvl#L~QT)J|OGH6B}s^^d4_@ zprt1=1KVcgwlWCBmw2^I^CPtV5Z7>Piz-}6K=M3=kCa+_`DCXnw)jO1RtMr?BImwj zjas{k+Yw?k%sod-T&Iysp&rmZv*_7K`W_4sCEmmYcq@l%WnwPM+|Zmh#cTUDXV9S3 zXP2dK5|(B_@hk=BCz&4#m+p)zGyZL5VIKnAN#{a}MH#pAMBZ#m3?#41tQpaoAe_l> ziNJY!Qd#AelH2RHJu@_l-txm}vqK5(ixjEUNt-R9MnNY-waI!!8E^p~#Gv6RW*=P~ zMAk((!?FOokeQj^#K@krC32&*RzIT&u54v(?Ql@Z?z2FXVUQR-onrasq zU2gugz=>g~rRTmjU8MMHSLVqmLAI2Mi~3HXo@c2`KW8x+MB&p#|75Lm*RPJsxh1LQ z4p%ZS0gfw)GvQ4*n7(27;@%+6*9MVI@fJ0$y^8L=dnYpuOBLKk>i%-|BQ!b7Q3txj ziAAx+0cT4XRzxCwEgzhKN^ zm6Z>{sijJI$tM?(+!~qUweA614xi_^1AMHCI)}kK&Gt8cIjN@RDYXbfRDaN=O?Cd#kQzA>ZLCEO#5BeBLWlMQ!Hf{Ns^iVz-pgZXgG zsSRy+Ij#48Gkd=k^{$_v^dmh&+;ttiO>frrhxuiO%PZ42;Ste-&Wxf3?n3fd!iTq4 zi&(VoF7#Sq_ehZQ^*A9hFaHUk#cak$Sp5`Og}`0p_F<1@eD(ZkWM`&TBhu;%K767z z%s-{jxyn^E$K*%8^Vo?TOvsdtqHIl{lDRmc)xqkH`expG#arHO^nYE2= zN=u0&HsQ}Xs|@RjU)_@j@(K5VlJ9@ywk2fW3zVwTJ`Bp`skSa@s95JqOA{BWk^T&} zXw?&-0yN9`lCBaehhy_8S54R+YCb0^QS_Z^&&^9lBU5}CG-kBd5+gFPf*vNU8vONy z96DZlIw(!nI+5^NhoYwVZs$j+@tv9Ogg0Hl?4Xt_y5Ke(Gnl`2QyiISw6&F9mRZ;U z2v(anStEZVRhc#V^Ayi4ZcPV*jD(uP3=O&?lD=gCcb_e2@6cd^bSx3^#0LJ5CAaeJ zC03+uV#owO@asVMsUR4{{>xim&5uVmZ;-8mvsE;aEmk=wm7MTQzgB|Mnd(ZxqM z2Pw6AX-P-u{j9VIj>usblJI6w7!F}2Oo!qwZr{Q&lI4sB5y`E#`}Rx5;-Uw}w*`g- zL}$nf!j`=dhTOS7JemQX)_+9dP2P&)Hb7j}@)&i%OczGu>-p(aE&aVG*EMI!(z&|4 z7v-68p7Ri1vi1Eskv%&aE8>%PDKUT+t8@VP>9LtJCeu8^n7-O?Kf3(Rr~ZF3T{n2%sAcBV&x6mj07>*10u8ovBtf>buJny9l&oj zmrTd0gV`b}D7wOiQ`cXVY9XKda6i^ZXqmTAFfv5yi8cQL6Qd*+Y^uQ&%jEST<|vw$ z{1{JMB01lT!G-x<%f2icPWNl)Z*+4A;wOo2B0}n->@W{|_e;1BaSh5415S@{8_$R4 zFqy)tPEHQ!_+c#aiguf;5O1u-X~Us!R~YykNEY%|t{apGCR$xXHtz?-%OB)`j@chr zimDP>X7qC{73uEW53L3L1#2WnR>BO(0)~gXt7BQ_ezpVGDAjx@o#=xha)L40%B$JI zHiI<0c?yP};Ox9xllNzx#~NSBX16ya5!R2}ctE7Bz|y9#A3%7UMZCaXvcSYjS8g@9 zgC5!9b)&?39H*9Z3F(KS>IDL|pe$!T2HS+=z6ZK(dmM^>Zb1Z}+b1u#-i5m6gcfWv zqNOE7* zR-?Ap9Lb{YWTG$ewYA@e%U)@SPgunv`VBja=OQY%ePob=s_kKbLfclMB?jm2e?%Cp ziC;90?g5QcHtZ#GL{M_4$brOZQ{>*|_5k}0ZXOQ8(~J1P$}!hyuX%d84Uw7&VH{|r zyaNfG$b53P<4?}|c1hAw`Q^SG^*L1ylVSpsUGfs z)Wde0sF(WgJ$uYfmP(Pru~2-Cxb0`3`HLw#OO>34zhF9igHhGA4g?%#@yo1NA2J@BB$+tO8?a$oiIV_V(z#@QVnGN8amwY z1q@yUr0=Z-7PzK+usK69zTs-+XMgkXf7E^4`)wbtX6fAvUK7e3rz$zc;1Q8p@m3^` zqyEBE82%`NJ}UZP;$KCxam*HaWU@q<&4Qo3Jkx2PJ*6`Ota6p;EiGd8i=XPplp8Ur zC%(GQb40USjIqk0HESZOAeh2Ur&TCloUJLg`i!yY7*X|vk-m3784ArdZ8sv~kr1b& zjZ#^g&((`#3#8FUL6Np6lSP9vI0JRBh$1}EFdjG@56UN5Ef~Uc$J~OR^-dX#9Yf{N z5a}L8V54o#c=L1DWTC42En#F>F22?AN9F#S71i34EG0BiFV1`RGq*J}U()xYtxn%Y z(N>?XzOJ14Z8LSQTQ8Gs_#K(4U*lJpcO1l(-5$WupuB^e=f+Xx=E~&*f#zo{w2Q8y zrQis@J7l85)kECHY;=|u-CFpqkx@aJwW=Px#j!Z9e0o<&GDxzKv>+UIh@gPDZ7^Zb zl%RAh#`xtxJ0!PT+knnsR_nG_6^TPsedacZC?!y=6AN1Yz4 zoClRdLzg^Y3eO=JDs$wA&tM<4;eNSCIALgExpIeU|F?%J)nE1xdDpOFIV$X2R-e2p z<9#sW`r1viTe-x?r}#4{c?DF{@_M*5G02Rgdc38P9$N?lwdwvt zU;;8AW?X9kpd3va;&N-A@}t7gf+6#+{@VEqiQAg;(-)|q&KpXGIJXy38J!NYNg>|k zWR0Ol@u8MBB%y9k?!{1tM+PTP9VSd`xk@KTn%OJxVKXC?(vb<(M087_?$nlbJa>+A zs6RsqO|oYvw63_PpUt}7V5WlJ0^R>jF{JEaR!LOQwWC2~lo%TaYf1iYfkqpu_Fg@B z`n=Ndwt85mm!vstLr5E-slT*qNmw#tO0CLMjq0oVJCXd+OfFTM9I*IIy0_s9Oc{qN7m>kRQmoa&OGFyfnknNc zKijTI+|6ku@+3$52azUmhl6S8&U3lHiK`Ak+5@f zl=rV5Jb=33{)bY#zZLk4>rs=j5ry};z7p(7*2*r`iJp=k1ANF)xh?CR<{*a$=6z@W zmL_E(KwwMuRUHZtJCPt6nAF;Wu;k9_FYeF<-MFf>4^4kX-X!=K14BeS@&@qw-NvF; zizz<04YH{AgxHU`$~A88IEG!pPX3PGoV&QH*?w9}E*ZUt#Dt;`8n}s0mT&qd+`3Vo+olHGVBgwd~OeDRfo=B}6 zX;3aI`l@$k4Y0UM%)3W9Bdas4v2*Kq5DaMf|BSy|c! zXwUz?cD-G%fpA19F$jN)@-keqwYZt7%?`WB~9EP&CT(c30&47^))m*8Pw2Pqxz9|2{VZZUWt4{ zaK4@B_EKGp5`3`aENpAefw;86*Kc~r4RiZ@08aPMeGHPPs7IltMg?I&#qbex==Jcd z_I>4l8H2&jiY!evVP$d&J&gg3I&qW(BH%p^s7xOA8i-XcaAyov(d|F@a|A3ScdK(o zqjI84^*tZTXL>_RvbKj+YJFaNJWZ9CUNG4ARwW2aL)xt~cQH#RwJOv-bl!Tb&tO~* zl$X!FX5@TW8>1CfiR=-KLrvBSEmn|`P?_`V)HKT7(9)WDo3!xe-&v1=O#+3MW3=f+ zN-0o!6hk8+2b3W+bum+7LH@W%>u+mY2RSCirz!gB4}Sdqxvy-D2bQxH%l+M`t|o-6~?JHX>8-0*AZGd{z@xnaB$#o z>1mC~rGqOXsS$FkRL4jC8CO$ZO@$>-?9ZIPvt&^3T-hTbvFBakZ4tn($MTy|2$** zQTlq!4N1typH`~xd$?Er>yw%FWV1kSdPxkxdW1}6-#G1*ZApAqie2iqX&6RqUcYRW zMYxJx6#a=~i!eSG?978X#B`}K_a|UW^d5Vp1=83!oyY6mV2)mU0h0r7LBWzlA%R)> zZ(Op^5$+IVv8g22BV38qxcBCWlg~IoDHh1h6szdsf**{Z=vb>MMyIDITe(VX`-BrN z`1bS8U$jVEOedv|!*_Z9)gScG<3KGYdgy98O`Cm>2Jy`noGZs)o7JQXBD^R#rr2gs z1dVTsj=`g{wBZk1F;s{asQAx_-Zixehz-F8zX1(!CFo^o8 z+Fq49$mOCq2jg3iJS0UCLg+nvbB3b>x1^=6rD{1sC>M4Kt`6gP1&OzLzZ&wfM?STW z>Gre|Ntgi3C<)4UBgrddmq-}U4=!I~99zQTae|1Busf*k{X7SQBvnR(X*MDfi&k+4 z>(}NGvoCvjiH2tTIijFj{}=_t?|UR#vuC9ZikQwpu>ql%lGNUsE$yYir3EMrNy4lr z{_O}9iR!$cxTpALg}0@Px=@tv4}*$HRzfDcPg3BDR{BjlGaBs zX+)ZNFOs-{zK>zMLu*x$?<--1Kmfz;bB4H|-rYp!Cu`ica*7{tR4mG^)p(e@c?eR~ z=VH1;m=xb@>uuH;E60rgp{sY8DP@xVcM-c46KC^aI&!=@nWh%G1N3g-mxI3#pjV4^ zA)*lDFTx5TkrBpy0%*qk?Dr0~x8N$1)gqn|MzEr^Ir$n*UBc*+H#2Bk6l#y#r!Yoj z84Zp@hZT$*omu}0xs<;N6xkuBbE(@_2+`-2>Y7aIp@=b;5T$i=_1b=*p*UE6zq{%| z4pg5+#PUSMU-^HXZwXxy^%RCX7E9dx+Gcwjip|)`sS*wWH&C3aaSyH~M8jqye)oxg^@|D>5*vM5ye^G4;VKaW!_Yk`{jwYv>BkYQQJ)U}h5jq`x10seom*KQLqqc{2Icwx@dL0pEh;hz zN{filW(u!pKx2-`dGkxMQN{V^`_54{UvkLH9h(=UFi2 zCL#jUe+}g4L5}WeMP-GGhr0KmmkQ|^J5=XJ^y~D!LAO3#p8a1>##0!;q2Ytylq;a@o*+ z$*-uEy8V?(6tqI(+@G;*80ycZ4L&@=#^RY+O2iyiGx=bBvL0(Q@??8+p22QG! zw14{x-e524>a4O}`09n1+eDaEIQ+(AW{S14%HM89~O*fytxQmjsbmqwD5?lCr1 zCFasu0mh%1|MZ7-n=R8K?@H8R?<#XFPUOHvHH4^_#ao z=XUKtcwaHPB6lFd3N5aZgyB!nXucwYqR91qnTQl2UK&)2Pw0!QiSF^g!o|FD!W0Mo z9%K%gqh{Z%v|vqjN4d^?djTtY^=cA#m-F_w^?jpTQc@O<;<3&CT7lN2h~tfk+zEZF zi71)XEa;psvL_ro;+*juMeae_^SkWpZ~0=@-m`fkch|>42Uq1dAU=lM#}zOR%sY#Y zjpT0EYLWVFtDNquJ@!EuYB_Yc-HGq)%Pi~5IF#zG^IiEHRl7?gU;Z_`xq661mD%^?&C`=S_KgP=<$`=Hwe_U|44GnC>3odBye4PUD!aTyR!5Eurug=Sf*we!wFk zU1WIw`peEwCW%)SaH$xOK5z-oP);itxdH{0(v=>(4pW}1d7OtGxiW1Zt$zU3QuupY zjz3`GcVejOJ7Kh-i!af~cgb#!5_6>T{tXuFq1!w{%=BE}7(&7kxct13-m+P&zmqnV z*@{@cVZY?%Q7EQJd-FmYD6n2b^1A^#ut}5>zs`MYw?kl6OK2NqP95~8nBJvpmkQxn z8h*af?3S}Z?&#Ol{c}<~Gl#^UVFi9RlSq#dQ@s-k9bJMEIL?*x&FP}wfT8vJEt^gi zJM^JHhKr^|86_)DmoEpc;Vw}B`pG=tehYhE{)EtaGO_p`?%JqpqJ6?^0_4y8EzKJqH;>tDb<(ltk`z$Ayl+y+F`n?;XjDlJ^J&ek&u)u6 zoBXjAJCpCKZ1Z5{2BGXo)?1#|dAU6sDRLr!r%V>4X6*ibeQ3(rf+=y2tqa`Ub7T8T zy6o>_uEzofw_bl6=eyIsuV43N!J?n#x=`*GOqckEuDqLWw{KZ|79^|;SU9q8JZBBS z@@hfQ`A>0RaqIcCb#`Vco~6I>oOGBo<{ifihjPGPpzSfd-wY@2~? zfwfdEOHj6|a9=vnHMZc>&JR=uDH6qU&*Itt%BT{(x(<98s*7Y&wYbom4ZX`dOy}Tv zHtH38mSQk|i%K9RU8tAZf4&?CXJqoehX>+LbI6uyaVQGM`kjT=ch~1m?cJ zr8+`SAp%wDs7)m*XFCTyij@Pg!DC4q8`f`5rl(N7nZSjc{UWW}Ha4R!_>Y_U3r<^m zw1>{w89(V~z9t&yD+X(abUl8WnUQp5a0u@rw2^1yF`T(8b9WGz;<;va_|r6QJ<5+$#yK9Hv`U!8IcrTuOI?epBI3y0*M21{eGy!wJgFn(p={+vz=e>04ek$hQ z=VflQO^+TjON>b0-Q#lfuHLzK(epVbu&i@tso~+y+fre~ z(xcAIMn`|Q<+vW-O4{&?)!Z4@UgGiY($`xGmN^}hwBv-S1plWqB+5Ktr6wb%^QHcTRypJXZT zwk&DH#T+}~T-wQrj+XB5tquG1kbJS$F=MW z9|ZBIGn|x%atucwjvc+V-4bQ_<`XfEYZ#CuH!UmvKAZRbE1$(2K4{!%f7$e%Nje23 zQmwRzR!Z`6=&cGRA$I7JEie$oQa9g<+lcSn#4~Se32r5~WWRgBX5jxbj$HBmu3}iz zsS^E?l^j?ujpf{V;VFO2@%oHN1qC)`{QzS_oAO!Klahd2Ca_G?J|95}tvg$~Z|?M$|$a8T%isQcMRZ=W(h#?5)#(k3JHD3f-e2ie59m;&$3L|F+ z5)8f4{bqfF+6FcZs(LBTdtR(xo3;{o>A#-HB$x(MVLCyf+j~Y`SduXwyKe)U)w7N6 zTbi8s8iPQu4}b+%7;3LuKe%@oimJclJT1npOLw-#HkEnPpmg7#j1hL~@XJ}r;>A|$ zhVio3rIv_5=QUX0Ql$U-0NC^x@tEbQ%^~kO_jQT8!3%s>XRtBOjs@_}Vnrm5n3Y-d zWwtJ!(`Y^cr`Wj>Q6vt0&NXsehWf}x{w#(d=sww{!-{mJNwE3gtSn{Z&dK{19get+ zl;rId93;w{IZ6^%UK4fW$jO%-#`UfKm4J7UKna&LR_=oA# z{*=Tu8n)Wv<+1tc+f({L+@85FTqSY8voU(4!geO52pg-5v6Z(DXTdg8 z^U=F3O~#{=q9Y?JRuMln~4VAPK0-?}}O?m&1Jf_N=~t=4lZE%mqFI23W8sA|`j& z=@W4QiqcP_D&%5AT9oU1vPB~bgehD2S%Y6epTYH5yg2k-?oM{Wnn1io8wxIAlG3T# z)zvKx+l9S>R4%z~<2*N7bD|32GqnOgaYRMYt^ zo51o7Uyc`A&oD<~{{LCxQ;PZ*)F+mmCMXKTJn7x)aCx*h**bBWnxY z3?AaWmw2KzG>D@la>bdwGu*rEo%zc(|HUA!;e#+P)nbvU0cL3jXGzBIMG=cHiVNT4 z_DM%xM()NcAtaHj5RKI0k4M9$gp%9dOVW|@4=6`Kz*VaMXQFOa0Qzpg1Ci#R;)OyT z{bm!m(c(7zSdh4Sp%;E2Zn3QfnltOG_M1WBXmvD$qMs`or94yHqCCX6`*QRR`<*`4 z!y|Y&M##n1aVpe-vd=6Yn$?ZE>lX`zt{>o(? zu9F6!{Ik1Wi1ITiA(yOvuF@QDaaypMK`W$^6WSO@nGe4d+_ge^LnybeH@U;`?XMOoFu1D>Y2~YK(Q7u0(5_pd6TYu382A3NGx# zEOcaHdTiZy^`>137>e$PqUl5MZz&C}7~de=&?L8GnK@iPSL5Mani$z;Zm!#x9{CSJ zxczGmDIE~x817~**W`OdC&b&@eo6RYsbTWAr3O}(iHNC|nHkow2z~iM{3N@E8@}(V zWoUWa+&jrpJwn;fRrG`ps`)##W-PCDk5%^v*bmb7j;WT0>N0Tb{{`EO2_lr@?Yg{= z{bjD^K&yO*LnQmFJF{pNuH2v`hQrJA`N*EHIT9h=Fs)eDoEXi7dX2qwIDS9u%h)ab zX-XSuRGa)^l6O(W*VdEM6<@R1YGWk{9-(^hV1F9rvWFqa?`gRvn~+#thqB5RR8{?O1@Kc}Q8gX+VKrxVYrPwl>${XrXPgmZKcDv1fVI>~Co} zMsj>ls~8irg}69)!BAV1ltsB3zV(HVfu<*@`udz#;rQ?gqylXeELhQ+Awv4%>xfIv zG~EMqO&UT0@9JM^1dt+)(70l6PfR!eH8`kiu$f?utwz{H8!5D^aViUtvV8WXe)Hqr z-J-}x(Ccz&$3xWGd!{7i$COpNC<4+-tLz1|25787@*o|&Z zZZqlgSh4L3HXI>|(VUU`k3oM<1ccUI)?fQyPVNGTJLL}Xf@ zWGkgwt?tf4nL+{Y_f13!d}l9id}>HZK1j4ZaG;?Lp2)C-p-5o~R+f{YdK^~hyz;gn z{dy8;{t(pu#wn8>@CvSHgN~8l$Ne`4%r)H7kcYAHXnoSf%+5#m`{{pAjiWkXG$$K0GT7zy6hbe#u`{jndylVSZbiNswPpMlc-7&K( z&k7WMk9Y+4QB~xIcGN_SyzXY-Z_H{3__{gvqKE9=OVuOYXM{gp9M`k`R((Xpe5o#O zU@6Sxo;N~+s9;b#gdI9It4TMg-dcyt*1OgQPl1JL9&DR7!asKkcUYn*)3%Kx%X$wT zCbp{VO6CFw_e)l3X1&WYZZBjdE6L^~BS!TJ#hZyJq2usphvV!q#40dhx?IM$sZ1(c z5rm;Ui4~$Bp}mE=h#Ll>Gz!NE-)!^OrWYvvUFs50EuCj~UyU<}(5|~k%rAN83Binv zxv3)Wv6R_MusE8vn;7H7$7(W$CFPoZHS+69*twdnUmEG8m9^emV{*D8o~`1Pu-pio zMjSEwYWNab)`5C~QTpI@As^EGg0>;4{p?J&m`69jXH5@(DcsC_As z%10+5vNnh*5>7fbSx3JhPxf__96v_@$r$rGBb;>oy?2vSk^^ zj6Fqrh}P=3@EbMr$kxR%P6xMz{b1BG((XXf@LvI=RsNa7?B&t$pwi|4m>G2u^!@`G zW0a2n=)NCSy39~M*L{#8UFMsa<>~TM-5$lW*|Q-S2aIvjM8!2ru&)hZ6b|o4%c=;g zhQ`KmQFyZhQ4N&3LW%PVBdfWNKd&%uU?V?N=pGlpK-hAZD&x&+So_O6giMScpXfTY zjE;!X4YNEJZz5{}6-k%eWE-*Vnc|Z7QZP*&2^qHEt>JXAVw7T{e`sUk@T0D%N^Xz5 z?i3E7S8>d8Jl%I%K>YXxNys$>8nOKg<0r_>?Dl1t3HZX_VC-m=Uy~qa!Sh8Lg77+B z8(&fGbg0n&o`9p_n+<8#v_xn1d)|4HE=mv{MDh3abRM(m^hqo(ylR3X=q9fBvr_I2 z?HCt5t65$^QL^wwFB{EnoVob18kawT3ym?onnGR^_(68_`grj%-`KZbzC#k`XIc_h zBij>{YNH6L!F8}T#wM^82bw0>M<4PD=C|ugTT^jB^8)jWPtkJD8gBZrn5)JV$Kwz} z(HoE`xS%OeDL}$0s`74;@Y%0ll)?1(z)ulVpBmpj&~G&e9Vicnq_)v}k z{2$!2lspeY7vKwj{L{5MxZ}^K&g&{ujy_IH+uEy}by@0|CM;SyTo^k%e1x3GM@g3K ztCsH0H&fafPp{<{^a`B_UviJz&p+7&=R2e-U4s2#9GJ@>yuVt%1Oj(+S%FWhZnxK- z0{EX1j_XgKrz|DoQS9!v^h({d2aa)bIze>vvr8>d@$9>%%G6c#rr(ipXI#~7qDcEu zhjN{$YTj}%|7td2Z?q^OSv$7Z8|6A0wI&CTNpK;Jg}ird&Y|j&!^Ure%%BuoN7~hl zc0S|XGhVcC;_Ccrl92G%QMjCyrT3b2JVjtn_wxq{=NtXC33NW1b1YJe&ahr~D4UY@ zVPCD^w0t*iC!HTZ_rx#sZe73}pPhLAtkv+?i3WZZ`bgEjj>PmVFjaNwBdfjBI|*^7 zz1-}%SnRz|dg{_QWLwXQ54@wYOkL9IJA6coylS0gP1?SRI)rua@c{Pt+8n|MjXo79 ze^j)CXYz3Gxp!y(K*Z~W+h;T;Ny~b~qj-Alcvx9F84;I;wAF1KJsO0XdvTy8suoxZ z*Ko$YT)%{CB3kk(mwi8_Zo$q>V(_L%zr2>B=VML7j?N9>*yv3x%9-yHJuiGc+Wp{D zJk#y3)?er+lDsM*V278 zzs%{Z!)}oUD?h#?=8f^#g)0%2x1Ls}toyIeNw+VtsAz`ef!o#`(52iSKysR8&*H87 z>X`(w+w=X;F5)uZWmj8AN0vDvf_I-(>|FjjMZLV~E7`8gIR{&mv}H~8P$F$z+=t7n zQDunCq6(y8ll|+D@rT*re_fz%Osk?BU)^zoe&M4Q5^XK5OqZc^?m!q6DbuHcCvx}e1 zLbw0@lt^hA7l;dQh@Ialo3^zt0)xDb%snpInnu@r zUa$H4=q>+xnP4Be>O8LbR(0M14T!D+{Q?cD)z5i2=-%yXe8zK5zVs(1cZCMayY zW}Po@s?%cfQeNmco$5Gi-1ozL)IDlNiQahWZ`p6Cybls`pfoIKss;6#TcA))vRT21 ztoZKcTp1(MPrFX(*?zaav=f74tV+4Y6Ny>M7X0NE<%z3?t!f!WzVnZVlj3(S^5-6! zp?pKn4waq?I(XvLPtUS;k=rLOY?6?9d<6gP<+IUT&)53MIR{JfC{>5@Hfca^)lTiz zKA~RSuQ6SYvIF~`+6@XfA6g39W88&HNQqe0!(A4yH(hm{=`6A>7#sdPfs4l03qw(b zXSpA%ziED7m1g;bZX1dH?cBjzV;~=EkV>wgXunM&wpo0*6Opgd#{q99;B6IFm5=bI zzFOh7v{BAn{KIHO?Djf+3+3V;ZRB9VsOOu1Ol_`@1vQ8RFzYd69tf<`5VVf>Nz5QU zCKGn0M^hfR0ynS<^;4+~>X%>n>n$L!=4D3JrQ0J(9MM>0&QO){o~y1ux9iLfwTyZF z4_jwQtI{KJZGBN~ogRP9zCrwT@S%jGi`rSa$)j&V#2;ED85@4+q!GWRKVq(xX^p#? zrLwHLZ!b(JBtaG!mxpe|^bH%ZHL|j*cR^D9()ke946PVPTuS;U|)Zlz7d2maoT zUXO3R{mFQPEImlU75VZJ*cop)+aQ@sm}Ild`@Y*!8`^(RL_lgWJt(=Aun<=HtUE)w z@H}hB(Be<>@;@)p?1Eg1Z(SqP(M4~uIc^@PFFqpDDGnYb1oM5wjP+eQkXp;vmz$U`jsbj3Je;mnXZ3S7 zGAXI}z$5&fa?2=`WR=b22ORy)0KD4@#@Cy_11n7Y5k!kUat1Q3s|NIyyH&k;dm`5v z^#|?-j=4LX!LVevIA7i_k{;%RQ_CRkr$G7-I4~%k-}B)o+qLKQrYv0h>#zfp^DfgU ze#RLD-in9u?EzOY^3DY}0Q51+4K?(_DjV+y!qg8XESUy2!kf%u5DU1PIPzNGTB1SA z1gN6Zd?wJ18?_8VI*EM)5U+2K-Al>()kS23muX*#_6CwlG^V8v11@gXzS4G@~Mr^E9h(%AYnw#tTXG+B+v3F z5ilmbUQK*XqPbEdIW_QWydm6!fY!*LeBa*LcnQpP8OwLL?kl7N{Rw* zK&Jw$QY&geVEgG0zlf9nl>5)+e6NFBZ(ihBsty*PjN;1~*?eKH*I7lnU{HG`thi*% zi=y7AzQ~GT0m3-Y$o-pp0iuaZ7f`@g%c%NN%xaG@>W+o%Egs}&&Zv^&Js*p!JzGN= zyiewRC_$F?z1{vTL-m(+uUSb#99EC}*F=;QMXzAMjg$$W;vaUNAw+PrCB1ojLa^YjHQ$j!#u2L!oHJSd<%1{@V*9 zEc#~B6`n9ijYfFZDpF{B{H4a$7(YF=3tWSNs*-u`!C~hx_pg+F|MSQz4;jOOI(XR8 zlpiFaBrG6%dZLKMr&@(58A(L!jlUJQNfw^MOQ{k77lNAaV)*w^bte!wvfUkvI*cz6 z$5>~KNDbK)a+s%0AZrxezUIDH(FoG1@tRtXB9xVgN8i3bnECXf$hW@Vg&rA%1GH%% zQk)Qu|_E&! zNl&O{UQeePCK=)h0@@98IFV*#>|Bi1LV)a8Q9`HuRjUnFbsa+y=L+Af)S!io(<1Y0 z64&lSp2s{#iM-fu-zd^|iWiP&YsfE*(s}=M$`Ly>WdAVk4debI;>o7aE*HKXV~?pv zQ48Xi9#BEQf+F0;rPcyZ)_+v7N}4LE+~U|OcotY;1P}OSHTW?7;_~fc;MECCPZN#K zt8I3&!s9T2L?lTU ze_Ril&T^f)^K+*wkh_{M`}8m!ZYkw6TYnn)J%rKx?bAzHnn?2iv>@962=>xHZMJfC zoerNJqu^KxmyAY_nr6L_l`*az%c#ua{MSPW3;xd!cs@$YxZrzrKMrPbGJfaXW+EiB zzM-9)!uWNct@TJ}T-D4QqY~VUMys42me5O~mb`K?15HXw9Yhf$L!k>V>7}9e+1;M0 z!JE)E!Q^ln+{UZ4Lwtj+cMm0m6LQLloQC_iIqyfj@gn-qc+5Z9XNr%KFaqw1UUK3Z z0&gdgbHOtjrh_r!b-_W_2i4yN!ztY%Ixik115=Gd;%{3q0sjz)vff4-R_%uJ0Rudy zv}MQa2TaoeiF?xzm_Br=v&iZCH;$5DUX^5x7K^&+zqlijWt#MqR2(rZ)#~bn9k#g{ zpEMYeP)}2Hs`W|~|HB_G=ihsBR+D*0Scn1e?_<~<+Pr#X)yf0sM9nF-F~QL+c{7vx zym|x#g7hL^t5$2PFB#K4zNhxTVNyipGBMSU434D&rN;55kI<}(O`)CbK#?#DM`Mfl zRI@8;VerOo&qbllUIdKbdk*_rxxH|=>i%}~mfQSV`Y*MIBy>MfSrZx&L1Iu7sk>OL zep%mvG+Cvr+x-yc=f~0F?Uw*KJtiz#&X=xY7PU|Ur|(Hu26oe_VWsw_0~$029tAB+ z-h!o|4U~`r*!RA7Qmt{{nzs~*M4r)x30MBCJp#JOoXq}KeCv-zv-V*2%fq#lO~IH3 zBUl=9eC5wl;!diGz=uwHD667KyAZ#2C-P(m7md-;W~B-m|ATc9{@H0)K}xMroCnA` zk;qdVxF-s75HSy5e9!nE^FwzEFZpZ8;ckK;@RtkEz^Du6A>{wW11{BpA=^H`zgTgo z`jf*NN48(Y@c$pb_PM1tsOlFz=hk{(hJ`=lXoYe2$WN6{#?Stb8B*i#ghVCZN7-Nb zd5W549r35jsNI>(K;bfQ%2toOxul)9ei@+u24^CgJLDj`u>|t|*N}m*!wOIbD@6{K zE42vVTXL}E-;_!xA{L4Bby#owHK0lC9Tm`|Nuim=ZS((j5Ax5~67UVy*rsm4M3&JL zz%r45JpoOx&3pXR)3_XJ;o#Ju%&>c6Mn5&2zk0CcNPhc#@$fRVytB1tQkBxxp_+Rz zd46VbZaAZ3XUD#d!ok_a#g2>z^ZVfWi~zPH*Fxb8Jg9GR0cIL9JDwd_VrP6UCoOfn952u^C3TH)~2@N)a&>>M}6e;Ha@HGgsTf6G^?w1sJTa}O+9ox2Jb3ZXB3i_0A| zOT%p)nal03S2=n+wr?>ktLA1FJBp$IjeS);9`9`*SQ=_Ad;l#^E)5$N*t4(+!zTV) z|9zJuM_8wyo@jN-nXV<&1pEFK0;mWDp=o4c6Q-acHj+}^PmKdqcCzq~v@ zw|KJm!R-9vVnJ)cqmI~KulCx?>83{y=04gF-<_Z9OK9+D^J;HVeVm7mvqO8M7jx!6 z9g5dFDfza&SG~6j(>#Ec||WLmlMH)hkw}k+-Fg9{>5M3Dn%! z=wFb8{rQB%|E3(~fo)8Tc`O`b^MBL45|R}+e^jae2h;jrKIFgk^gN$%#ycvR zcV9zKhZ9gkpQww;P{V&^w(b5mr{Z6=>k~Y5_J8ooh9``mNB%>!Gd#g#VE^~3G1Tb4 zS52Ti9L7H_F+5=gJ@SuK<3Ei$VGjM5f&R~B9zp0|?$Cd<><#}b_5F|fy)%kO=>AV> zXOuD2JufYC4x&BAn`-lmzp8s2{k;mys zj`|;A?|;hu7w_zJ^{)S`TQg+I!QXmv$7Gb%ee_DlQ73L$OJCTSeoDA(iwQT2!`E~+ zO`;iPCB9HwXG9)GD8kt%Dr)HRpI<*lzSA8Cd}l_G#R&(p{!A@dy;?IZyQKb@zVNhY zrt#ejan~MIjk|HOVDHrAiOW*esRJWK(+pqD+?n;LoF5Ft^)iVs_FXfppYrX~vJSBY z&6;Jl@`1MnU2ds>)h@10IiX4`*BzYtLm<@jeq;SPYUC}MlfT(QKi^!)jBn|xKYn9p z=J)ED58rIvm+f?=)nlLJ4yLhv6lx3Ze{OyIg;f8g*j>h2@{aeg%!?p8!TndT0)~2H?6}51%AMNW}_Y&YM2so_s@zbI_basG1R_%%HZ{dv`hD0^unDw z4%`bFXl~;;o&+h|D6jOizho_i+?p9Y=~MKpHf-fyDdtUMe7{oCveDtxO>#aWj#jE7 z^JP2;Ic{3r__DJ8zLlEJ?jw_3)*mqUi2g~UPs`^7>knD;Bh`;)-`Nx#PG~=Jpyfw= z&5yzKl+tM(!LQMrs~SFXH?$p^v@`Meg4ECuesyz zeJ}E_ABxNxFuVHZh=dbGxK2H4tp@Bm%z{9{+is?slay|NCrA56Rw4c@0M z1WlClZhkKI1Fzy@*xUS&3u@TGoJR=hF#=5EuI&ODEhAJrEdSx02~ z?owC=i+{NO_wMB2S8C5(hIgM^RQTHUtWV~nwMNf0AL`b9V8`73xn%0(bx8!6+-r5_ z_X`c{!K24vD)$t37{hJPk%tX})NRgUW6F-~H4G->UQnq+mhLj_kd46o zGQGCi)}xmS-%Tf%E%a>Gx33^{GL&Gxw_=Sa_izu2cHWE4yHfh+ZHn})j!c{AVeqih zkJG0J&bA+H2O~ecdA|P+L&z}fPM5~bu7!TR%LiMp)>NK8AgV5?y|naX%lG8v=Z^2x zQ#|9XQZBaFkYWB8H6^RnJo7Ju)+>x|I(=3=D@S}d{=%a7MAWgcm*nVS8L9TtrsFzi zrEAiQ-s;j_s?W1+dbTJ&AL$I8xa!y z)T>@()Z!+694gWpaBVvcZ2a!p7)89*YP|m^IAXXX^71*#&id@E|H+s84@&p`I&pxu z|L5b&Tk=XKXXC&6)Z@fMnHt*r;K#O<|B6Ui()H8$MjpNsenuu`?6(1U`5s@1wmXuL z6V?8k9eq4fw@fFB@kk!Akn1A8US@h$n#8Rt4>$x7y&fhYVuWra{CtT_IXlL}N_@w%Q`8|=)aE+>^)t+62 z)S5bMRg}4Ow0?QRqc02yhHMe#x8>WnmX|Lw75f}3xThd}W%%vGJ<1BFFUVJ%$(#@i zjd=d~6cAo`&b2?A;u$bU$wx0)>BInG}S>W zCwDD-2{^sF%(aM2%k%4v-b1qxKYb|LcJb?np5Wln#Au!J^_BWVzL)IPIp(_#*~6%# zrNfJdMTHB(zb>4}esIFg`0(|KpC$4+2Ow>xLx);^Oy6~H@`&l(FLF)}#MoJ1tm@iO zv1sRBRk_b_9i*D}S(%)vIU!#YIbOe7zdMUzzaYd4XSTY(`8#FmBEd0ph|M3&U8 z_iRvo`DXOYTi&(3xfd>`c zVX%u;t{M#fL;fMu^hYjH&o74`F5uU{(%K_`Zt|>{O2<$eGxnx@shIw^*P1CJrJrfN ziRWy$aU~tbdMb^~`QWT1|ME>j2esvUO1T(Ws}Ivkq&6{oN&q+B!&F+QX1ZRHX3(-`f;e! zv(Q{DQe318uJ1l5JY?7{5*2ox zt4N&d^Q+3JjO+?%a=#Y5lHk+$)XgQ0UyYkgjVp*yAta_Y`xTdS!?X|Yi1}fn!xrAz zSG|-z(freUFKnfe|Jhz|(!nd$xz^X6ri(ZDiX0^e%$#fEhDy6+px%BRhkC7^dD11r zFT8e6{b3_lTX!|O=4_{m?FE^j6>IGGOUy)7@-#v9KFIoUjkdr$zS0xp$EGw&j(MD0 zbm%vi_0VlqT5;%~-bCLW$irLh^VZFJK#Yq|>Ln<7O23#y^X2>ju3V9)*7(=hhsHM1 z4O7?^*pb)ImcWDXx6S#1$>2)Z8(>%KhH z1^PSdiLfAB`TJRP&6wAc>4PVP8?PRF_N-dI&S&=z4E!Fn3G4v zNAWo|-cPWmjbx>it?5_(7Ure1hUtZ&Gwh6o(?VT=u#Kodqq;1s)|bnVg`HjpuDSm> z4suT|3^`ieWB^)dxHwGKN&lJfS<~=dfOrS$VgKS2sePP^A9Hn2E+$3_NuIswHt7wv zwf68eqvYurJx$C}497ozcjabj?q7MzEnFdgNziejcYj@L4f!kXB53UIGm0;>17>xr zCNuTwJD>U9Ki;Z=ZJT=!Sr>^f4L4DtUPy{Bbel1a)^0>_n2V?Gc8N$-*3(liSVwy{ ztrk3VIIep{EM7Hh;>(lgo|TQWi@JRGNz(*sa^u7qYc+6#erwQqMdO`ccN;#|{u!$M z+fkIvg28ST2;VS25T;qKcGu`_{^2Xs-*b=oKOas!xTJSg!o#SjEw`_JO|+E%4qRVneznz( z`hDs7Ud#OlDg|EW#7d=Kr0MK|F53yCUs2A|8$K}8ZW)9&`TbEJo*|q zxwAUAy{M>k^5)B$W6uQnIkrV>`1bG07JuDLbt*n|(V(`RWq7|_0bentT7P6xtHj9T zMZ>AXQ5EW$&6D4{O3S)kzDV6Ghb2d3TxUq?23~q;Cusf`6Y?-SrO^oy`$zoKZ_4ZN zCy|J?wR6R}%d(zV+??YV3E3aZzktQQ-tuQvv>i8;lQQU)&Fh+V7#~im#+E(P{4r&d zsL&Y{ed1!Yvta#(?&+!KjdLDMpE7hf@uy zhGr8h-ltpg3LYbx4`@WVE-5yM{Ay4;MyvYLnUAdK&TL;PzHaF=0`-rBy?JM)TO^+K z`^&h^CwTg?FN`DaH`oOqmRt{hf3vdMdwDWgMvvHk-swpzNv`S33T(bseRh&Qsk%q- zuXCw4AO7E_`TxmQ`+vy_-~j^u!wN7mf$LT1}t53zmzYqO~w?PhxWOj@)>_qDr-70^Upmro2%Um#tJv> zH9VB=gGUStJw?^!h~rJ?r>gj8=2s>M+Hbk%q!AedDRsBT{C__VSUVlcES@VML!9>v zLt3!9!-}_WBf7G^T-N7?1#PkX^6vaHdqn@r5tV;kV+S(UO5NuG%INps$UobJ5ENDs zhS|QhEq5@=fy5s@QhF3-B-N$%EdWv$I?wapuoQ+><>UzBa$9l_j2ukCZj)jv(m~LT zX6_0kbH%R%yKKA+!#sq}Zw2n!FY(Yj6@5Na1W$M?65ZE%H^9yJ7$>2#yQ&+0UMV{r z^5&kso>I2Bcis|a-_{Bwd9&k0a<(b?+!!R@{_KstntOlVm++Ptl7S%pmO*q}?7o`V zS?6@ z*XCCSW8;tSApq!2##Vg}kOL3_9t7o;R&ZJ1_P`Rx&x^wx>;04)wDn8nz4bV#+muJH za^Yxd+?RiOfE8(_be>=QgmpR>Xl+r;P1{@$&L4;&Qi;j3E8Kw<3WF=v(Y`&!3rf#4 zDC1DJfVM3bi^W!ln}xmdYMDu6p!8Vn%qLP}DbBh;rZ*bszU9tflJSno1O8$C9`ox% zr8Fvmx30KFWz!7@(MVI7l-3iCs?P`i8OYfgffMJ6A;(ByjrdrjYTAgFD$c-1~vC{~> z^|4rlWoJJkxfBz)GKNSQU@DA=l{V`N+J`G3*I*d2XiJ=IXQiOjn}FLo`R^@s1cq~M zhb?h3h(?g^^|MX&{FZ{kU`S5U7_9KE;B~nJ-}>{{np`ZUz%tK+*J=XaTR#d;Ekhq+ zy`*io&8CHzmL>P5G;o*G!V(8NP&$JlIye7a!RLLHdhK~#W7YLVBPS<7QDoqb%E4qc zL1B5*K*7a*a@etO48OeDuxQhpjdEA$FduLKLu*OGb^_jr1yw$aYryc6F2Zv_m8JPU zuk#_6J_=wvgjFf7KxA>>s`Patr@Ku(;~%O;OWGQ?(i!LD4CIkWArUB?Thdw|Iqjq%(;ugm z1D@)2nOmm3>bnwOoZinRPIe{KL`|?*De(hoTAPA(m75*2sX58SA4#tY+dI&gEk1pv ztgE-K_PCYo)lGSUdfD4%$QfWw5g36(#mS}fv%dWwJ-thE&)$9ggLAofJP1lur_*K(l`5nKmziD*3T#h1 zQ+v6UU5DqL(H&^7SNH#6*&K;3JnnjgDQxK8P3(t`)l>L;V`sRY?A|Bwb@JKzeq2If z&0G&8sB|HsLSAW}vdz}C*(iG+$eG_hla(VD!U0w@qYYU=nEQ5k&gwvND|!LxscwO8 z(*{aUj)UcyY&gG7d++M=rJs;WODb&&1vEYMNU2F@ujXRte_HVtw_DUAM2mU}n5 zKWz5os$JP}A3qAKyKH{GWReel2rSXlY(w)a`_<=pcCT6)^u&G&J#CAw3zF`xbk;x6 zPt1Zuo60$N_bk(sdngT<$UH=xK8$pKw5N^rPzw^5!#XXnR9ksmlKi(u52YZvyLb7a z9mtC((K3zDqH8I*WI_mzIh zMdctN!5Ly845S?9JR{X$SeT)(Uz=_SPDWAItY}Fpj5qvsw*M~Bu(fhji}X9 zBPef6`Ssw#B?3u1UvD4v3@Q?`CHYm{Qh9-ndu(ouz$)BmvpHUF`yA$~-!WO*-x(|y zfbb6{JS(~k3m$1p$iJp(A;<$bILL)uzEXag^OHtnwxMzpMtGYPq)w72B1e=LY>;>a z2fsP8??nJSHyYNPym;!9masifvg6bU*7hbyT~TdJqY0L8=$S06Xp318aCJ5D|zzTjn^22quy(!cC&p` zn#^%38#oBsRnFE_v|`ET4y{l6)DaQKVd^ zZlUo!aahUzQfipSbsos-V!R{Y+d}>t3Wq!QRK2hK^;gNw5ZQe<9(ZY}uN6k|<8s#?TvC?3 z&c~m)m^h_@DdW2qvjr@tA3tAg`7kIJfd<-$G`D(A0!Mc`7K|PY1unzju<$Y*C!G_A zyD+11KT(4MY^C9JHQ2MQ+iaZdTr)M0DIGe-VG==5Y9lbvhLsEZ%4!|PDohUXOjKxi z@8QDeZnN!=&Z$n0u{+o+vmqZ8*f&`nZ2jo&mb42zmomb(7lULg`q`JuIZ4EhZz(Ce zQ1n;U;6(6|J+ig2oAbG>j!5|Hj78pmC+Avw!1rM6BERmQ>&UPr8%n~0o_>+)k}1Rn z+xA9B<+6v{7mn6upYzam*rBYJ9hMt9qhoWP;rG;Lh!)5s1#P!w@Th$4^u{ez0=?sd zDKW!+uqQw1Gqpj@oYS0#j?tr=F^L3D2R(&`VteH^j-p3Hh}$$)${Yu1A!cxcG{c6| z2hx(K1_)fnvOlqvIKSQu#CC8P^tugpTgqwzFwj34#sYfTH>m@eSwI+r4RF_I(^q4+ z=>X$b|Eso#?R5&m0fyZhm;>SSL&9>l90UxrT{AJGk1<++RdZk%PIOK-4Hy?7M`ugZ z89Cr#K8e|AXfh;|IuQ+>=RlVX+U94?(pmLr?rcUsWpZeeTUJ8K0~#tAoE3|-_I5(% zb{jt@(=%R~L0ZrRI=8wxsQRi1<`7%#HlKnlQ^Dt~z%qm}B^SA**<=YfXR6V}V2rid-ym-ksV8y14jnqPFDyDPo9>L6#165OoD3M+Pqa`uWB zU)J6PcXI?0^KfgU(aggs4a}o^dE7?(BF$b*pEFn8fP_w9P5@y@*6K8p2qaU35?o<- z+}h4|hjFOt1}0i3>jqs4{c z#?ba5sn&D?GI0w>>Yq+nb+usd{P(4JuU0u{+~DroQQU1<>DK#CvKni+_nqOTJU!aw z4F{veBv-G_sy~5Xzlu~MPc_sHQLMTPrGfQicA+D}Ce)2=j4-Scc`M}ult*Ipjen{Y zWouU_Mn6tS#OPH?{<0YCnpO;kK0ogLvI!Ud?Wlc;ne(>8J~`A(CS*)^Wfd!2Dwr~` zl(TYUy$>#^3QiY3wmJsS!|Byz6C&YMVd%^YU+juJB(Xh5A}$M(TJGC8x8eR!_cPpS+v7sLa&qmT0Q3poJ$vdz{OcbmZ$;sW!`ZxY?hFJ9QCOt2)jw|3kz zXGtjw93x&>r$~n{7ej3%Iw}JWrsBtyfkt#uN`1nH$3q(`b_3ul0#r1!eT#!+Y$sN4 zf8nm8RzvzScsS1uMp!R;yOYXPfX+@6=O78|BO);1k^5jEih-;AIuT1tpsOkqk@lRi zgzd0_`*+O(aij*>pOPGojh<7nLvEab>z*&>k^2HOYshPbuxOK=8!cQ)=@Z>wf?t^r z2_LSFQh2CLD!I(f>`?7rFPpqQLY6{VvkKk@r#@lT400A!Nsd_dnI!R-TTX~VeN#G6gt;{*8^$O-Pbv5B6yUi>%baNh# zLTQ!9`Bks4(%Tj5Rx^X#GQ`X`W;{|U*V6quNj@WW6P+ab#1yFT>hKN9y4=mXNg){$ zOj%9~_y&zD7jRCMHrh(kAW`)v;^*jU=E^FN(Z>A!^|p=s-Hh%P z*X*vUV}5Yo!DF=%EJA7d%EHAnoZj3u!mEnky1ACaGikxE_T1GE+~DC^?jN2Fwap&0 zCH3#$!aMILObq1+moKz5`ePx3-PFmtTM5Cs@zN}ExM}k|%{H5mOkFnZuH3?^hS4=? zE5zA&d*h7xSpPGDtK>({kR%2-U~BG<%qk;t6ie_&uPS>Z>F7*7b}WMy=-+*8ORQg! zIdR*f!;SOQE2L#RPCqtfeM#R>st?tjw9$)?H(wQ(v&#vS;l;cSMzkU{!6X6u4>5 z#vA2JqM8|=+0^OW4-T5NP_9f!MpV1zpic5VvhjC36pi%qgA<-aLQ?o0H}UZkHdBx#@D zBRgqE4p7YVC%Lt`_8kf9#G^K;qivnxd3faa-8Y_<$oDq(UC>2HYK7{EI zIj2bIr=*Yl>G?0JsjP;71X%Lo;{ZYur(mlEfxwD5CAu)hF>@DpP~gGr(ZNB>owjx|Xv2 z$zUVWoKw%Eyl8jcqT107=aB;2e$6@DX(#j`I-J6Nx&0B0!4e~e)(m5)$X8wXn54Vt zu@SWeZWtpb+%^= zK(%!C$XUOvDm4#_SIa`;_Sm*~Ue}bq2b091*rmd|@ zLC$ZvokKmRx{%w%?MrW5>xg<76w(=-h*@q2P^rr+CF^~NOL=JV9K2`zSK?%G<|sqA%=$y;N8rY9rAs}pM9@yzWlL_Vb)XD1kntroRNlTZ z8>|oMnOrX|jz4{z6sOtjbWWLWkFQ9UN+-qrSEsbBw%Ls381#KGG;J#54b91d;B~>>!6{ZKYa*cwHG- zz-U!-3`qm|0U-S>D*2vc{%34zuu1<;e*V^$>(1PIxkr0d+eY3SWnZDu#REh(F%xGq z6F4(C6KSGk(*vqAW%U?V>TN&x0OK0g;xuz&WLyyw%x!E?eyj z<88O7ul>@aiI}IauY4-uOSzUe=-PQixF)<%q+#wUlqB20-nc5RAmIko=1912jkz=R zw!vn=eX((@y`xFqppHgBguTLw-OZ^cZCgwl&OV%xg-1c>My^pw>6c9%!HA2x{cvJd zDil_nvVe00M^)iPRXLBJQI}J)Dl>fRFCu8vOeQIzqkfw3-hwdS`x00nkX+g;w~&D| zS<>kq^O2{OTiY4?DGKwQq%arUt?lU}pY49_Hw2Y`k@9)j`LblUY1)ObM%P+KT|{^y zcy#%~uAJUj zFy`hCa;2~9gL^N|KH+SL0M>1~*$f-0qiGUT3bDl)2r9^81eOCO&%7$vNeMBjnlAJ8 zlE?JksJn%=zlmrg%-GGW!3Zb03QpM<)r8D{DCLL_vIRvP9Foh^aG+;8OhD!rzau>m zDYRqU{odR)Hm2QT0UzyAGqDjVr@~dZXe7^c4h&d=QJF)Klr1g>&b6}-t6OD&Of=sT zL>xoD3Y!fEHFVIoUDl-;xTFzqL)q7fgasT8&4ee>keQtymDCd^yKEtj$cF8BeaMD< zRIbYm&m|t+Ba^X%f=pZ1%uo@}y)$Zjl> z-Z59|C;^6}mr4-k3I1 z`k;SuOm-%8Bt&RLsOKq+?SYXnXgz`t<@;SC3dJNi6JOz@^1g;)rMGt>?p^kzRbfMfR_U(>`QAtMB`<~`KJ@yUKHE0u zN8`8d2)U@_JoH4>GsPw-EP*ajc`>zaVjxzrp2-XOnJ2lVvG>YwgFgESZ8!RqC}Ja*h{N)RH?HS!&e{wT{iB%aAfFN!NRHUe|RB}^JL z-cp6ACd5)TcP3P)8|-z`LdzNOhM@^GvIEh$SsYw1-@MS^nlkK}VFykumOx?y z&(=?=kdQ+asdPiJi(SywWiwZQHf_gey_&wdS$*QX$et`=Yc;nlNP>S$O(lttR>M*Y z>1<`xDaJ0xln^+x`z=!YfqgR}%+0pksp?twN@QYqGv6=!1~waO`^3qzklKNjgC>t8 zFg{~Mmis$f7X&e#pFHO$MCe4e2cmPR783H_(!p4Kd38O>2z3 zjTcs&X=k~2^osU0o8}~-j+q{(YaVTBP`}~K1+F_W;U=hS8w_wU}f3-iLY~ze(Xo`h)Yv4>&EU^x>+B5 zXcXB7S2~{u&a~XI)8F#!7#9@xTwvEq{0MitS!1V2^ysr2Q?HR4wCM0(sh)9E7TR`8 zaPrPXKsIJt-mVUGeI6@N(hF))Om_il#KmHouTlA_!Xn#3i| zu`_5C#X(r9{0FwDzFW?8Ja0Key|VEj+OJ})gSfBFhTBroIDV#ey-I81rvPI~%l6r( zDn8AF7Ph~>TLE_cIFI!H@k+OyYrzQ$ArOpx6CE64IRtdcWAf8xz`XU&7p(Q=WqSYm zOw4q!>AXuS&(zKdiadk2QJ%l3ZjC^tP8aq+>I~1p@K^P){1Mj=2fgPF(BiH`4t#$NTY@2aD%C^J zQ|%4O2$Tq`sp}n_tMg$o8gyEwO4ZO&-nTcJWtFO_Q6`$Bi z@9Uv3CpKopn6!o7BZlM%l)*UYYn|#GiT=W%_ePMz5tJ5VcE-7mI*7tHTQW|LG)Sd< zI`+c2dSr^MqioHgrOF6Op}{8IlUmgMQr&bdE0aON;vXqDrs17SxZ!!_RxsAEwFhF% zB_$j7^`hgX0W=6!9ZK!#u*_!4-tPQ}oA{hPc>nO5l(87Of+6WerIZk%M;;T26A!hz zMn&*marMZxIE4vHq+;QG{ORYP-S8ijYCoQR+Ycp)TaHby@8-z1oCl8ztEG&=2Vu{{ z#^AH2jD^jQpwX1&!4R9N<}Q%9Fof8;{Gtrh8xndKT0zW&^xADre7B{z8gFwCA~~5* z8k%u(T<|NA(Hb4LN&(?Yih?VN?D_&(fEWCEC%%ig>Uu!6e<2V^A!VS~Yjdev4NDoZ zq#0ngeruiD?>$5cA6nTyEx?yMov~(2Qbp;EMB~!VgU__~+@h(Cske-Xpz26#kA`z+ zoa@QwYWE(>7P~X!+z$V1qa3AG-Bw4o5}+nmpx2B`ItCE>9c!KeE|aZbG|~*+UFnhr z=2!HvRFi!AgQB*8yJr03`SC!PdbVdJ0*wp`Czd9~SE9eddjVQH8_l5w%}&Suehfwx zuuw1>r$G_@BWh|!w5)J82tc>-fwxNV(87JP9NvU7DT7jIacWt;D1R?484)Zks_RNhO~8#najV=f5Y7ma1-2HHMzTgyPh&S`H>I;o zrMZeD$kNwFf3l56f$3{sdQ?V4INPA}d6OZh?-rOxx+bxg^SgoBp6bTSrkLB@ZNH|> z%a8YM6fTY;sdFSrnt0MIqpsM`f>VoRb0E<4s4AyYMv5|{gM{5`V6>o9=-xn^I{3i^ zr*|ojx3y{v?0%(ykle|LF*oRTFA@nW+nA>ytp@RWWN8ZQAzvu4No_0-;SBY51VEbgXlIEIKC$>DT+HrVU#y{Ae4F{}|CWv6N=c zN>+5T`GjbYX%@V;#`)(c_#gw?@`6CRY zI>4+MBYy<_ak8_SE3GLR-GKuBsMsFd#&8;5XKNZMLl!&=`r3YPIH#&DhwLEMGEJ}R zk{{Ju5jKgT4M+w+*{Jp@Oy`0iHPhnENdlHhSuY)UZ}~>78JVQW+UN=<-#4wa&Bdm31@)R0Hk1 zDjm6HSB^MVaKSGq}`v%xo4z=(Xe?S_EmROQY4 z8zgX>U5-R!?1GgE+DSc60+}~gCs%p?t-f2BPmz%OhtvEjvb^Z^-9Ru}1h-yjJyc?W zQ-IKRoO@A5_`LeTa(N|Fqdc&bO4Vk!`pd8G&GAdPq}dw4kW_8fUBGlD^kaS@apg#!uDMgl}rSi}V zJw&0o13m4Ol#~F(A>-_gI_&;(gnki9UFb%OFCJ>$3Z0`Y)V)zZwaGLC!-{d_KZZUL#u!=1wuDb0SRU!0tuGJ|X6k927+-?*hE>DCG@Fw@J zmuU9PMV}mIvzi}{} zTu4d?wov=*jocWB)&+%ybXOoYdno=~9uJi=T_=ayq-$qMb!T@e2xUT^+95{8>ZXYz zwSpT?s_aR=ZRJRRcb9%l4a|Z(=jpjM? zGhmZJw1~Ypm7U<+NeKhsmH@z;6Ft>Wrmwuft+H6cRu(+}jaq&$02pYH-1jk-IS``9 z0T3j$S^n+8`80SdFr?^uKv)|H>8l^iSf@GRqL*!G$!%DCO*MCg62w_Wbl2%&tLNt9 z?F)0@HTfAC0qG%FX=f+BW0m_hX8gf*luitP@nyO6R-}b1uI8unkTfBcf`FFSwb7@2 zL7sIa5uuR7fzB4L$L4XjK$_J9A)4dh1DOq-l+)$iBMY25j3_zV&W%Zx@N6VVZnq09ANny=VbP%m3(!>#Nll#>Au-_nJO&6iX$>^|2Gq}n+5?UB%q}qs|ROVl_vKdA^C4fy8)!L7O#^0NJ4r_6X z2gTwdbi8Ai?bEu%ZaNdEcH$3x)I+;$OxumQ5gS+N5J&exU*=dt`MJEQ0lHSD8zX3; zGiSz~$c}v!PMu!_*`A!{gpR<+P*c?{$R19|x$)FV?KH0X2pq4e9J0k}!by7&GmS*g zbWZ?5u7M4}V1w}#`*ch}=Yr8Y&Aot_x(P=85nak({#s!OXk$3)$@3^xr&3><-?M}*`FU;x@E@U ze`Gt)20q$vyYaPdj=}rw7mO>I`(MEDnf88x&!t5k{F)r`krpSL6y7MPnkr@LPOQth z4~Q7A;*v-c;!7bP?4dVaELb2RZ+d?YAnPh)$J}Vn14HGAZYh**OX6HR`@ZrB0w)FU zXBKy<^40Zj7K0bME5TX#IOCDz8E#I`9nkm)LQ9d=8ZicouUt(}&F+y(RY<^Af(7N0 zN9@WPRzN6L-Ha$mH^EY?vpBv&Vo^>-a+$}etq7x}KGfxSr3quE3G9h(jFk{>Idwac zl3eEEc09yjW&2PXQae=6Nln~Ar8o?AN*%L-1o_ky z@1Y4_)?CEHc|_%W6$PQT*i6V&Hl&h`)QK7Bxkcf0;}P>QBhKgh^j9e&xCyRY!vbfh zgxap)0}Qxh1}LP7mYrnkcK35514q|>?%F{<@<-^>T_VTYa)0XK4$ld<9Es+TaHg~fA>)qd9p!x*#)&t&_(2i$ z#^37UT|RrR_v|fBqsGAU5JiAT7WHh03}& z+WyEN z4W5_b=B>*{it+Hsbd>gcy4;C7%8JHGq>cy!mCEN1$H7{E_=a6mW$a@8nfhYAW4wV8 zK@n*a$Y;!-?6F79RR_`>6h0}am0M|3!t%|>5>6(uq1}rTf*7#hqcxnZiH`+qK3hlw*)4k>qYD~Tg!z+VNFuo;=VSV2#K7eS5|x$# z&FB&pN~PxZ?w^2OJgD2jRp4QW*1?T!X(FAkm2lCzff~w2d7ERA@4UL z1&_kNO@WRbgU5znn?VWggV^JbO%v&zRpPckuSx~6da-NS3zN8<9TaaXm~S|lF2J0{ z^13-%t#Qp%0W4F4O`O2fazyVfq`N~N!Lgv6rghno1oz~bo&%e0&7?K#h+rY&?Dle72bFs;!HtcV;7};rK~iXI3=hl)al1s-SKar8O1<4|dXI zP*UI!9jD^Wl?g8~9}Nx_q$w9|oUii96kY*=&+l6>hRjK^-Dqk~{qW8z8>iYCH-3Aa zB)jUdo?KCnr2@-nIv?Ijeh$OhPeEwqq)hCaY#nTP1h=3dv8AkNW7`dFB~8@{H&HhO zj2pyiUt8m*Yx;h90i>R$mDw0BU$yYnU(NfUYVk%j`^R1yId%CK9kr2isM^K}S9yU; z;S3Ugo>L$6*Xp-erdf!}65J6qj^2shLXrJ=S4qk)OR#x2h1oXSL4v4t# z%6KDEknSS_$u!<_s7xO0clT$f>fp6WpVLYb0`{F(JY5PZ{a-Xac+^SJz&#&BWiCp9 z@rAE#i(s|&Yr4^EI{R{v-MhwQ6{*+BB+Jv}&yVAD>Bi~`Mu}#^W*p=1-uVkXcMWPA z%1_w;^)ql_Lgc}L@Jn5JzO*zWMZu&FoV06Bp0J!l*3g8TV58FU%!Z1ZT&`>K1pL9H zTC$2f6Akiq^W=4gf@y54D=t_!X8bT&1+15G%}ubvRb42j>4#Se!o-%u%d%f|umKa` z2C*)*?Q{-l$jv?bR9$|LRE%=1DS| ztXi1u2;gQOHXsb6E@=^F`#PyU?E_4C!Mw0_OxVUo|HgvNY|TW-Bqp_=-mS2{@C1@_ zY|=VBew_0UVK+gl~N9SYZ+;sJKY%lI(vWq#R;cWVSAm#ia)L|)v3cUYUmK%#_u`~J2b)R zSUb>8O^aQj2BQHq5DJ71Y=!ZBU%wrR?c4gt5tiD^bHe1gC<8#&(*`#e0Nt@$Dc|vx zcg`j9{Fwmi+fqv^dz5$7adUNki_wAh9r!0Ps3OEArKVaBBT&NX$V>;eUPpdlw}otZ zthDVvd28eEJSAKb`2m$*@z>nmwr|D0tlci?&@Jw1VXNMgx^)BFZDTGSj7doiVi+YX zj9Y>RmJR@DQWz)Gt0N0oFd%l+hizq2L{bUVK!CVT065VH#)AWZp#{wW54{5AkQ53l zg~)PFUj3GIq_&kBNS!Tt{_0q*Kq?(*oiwCoHM5rt)5EyU+EdkG98DSY>{e(gustx; z?9b6h2l%aS1Ix&;^sJ#Kt+l26u4DNWgM3{Jb!qjhg7yx{A&}^6>LIFuv=HvCWx;L9xUmU^a3u;d^HB&d5d_Ck-W{8UUm4xMk`4nEoiIm_dcfMn+N&7OzMCIJqOWn zC!T{KwB;xmQ+gE4S0TZF>g~6qj^)#{H#!!!pONpNo$2 zm;V&K?R&F$UL#NAj;cY7Bd_w3&kdqphDd%?x*>VFw#?BXN!D>(*WblE|0!7{8wyCu zDjQOv7X*sP()Q*6PsHh;!Db|Xwba}Ag5J@~Ukt82NV;5jB%J5jx3~OItUmOPP&x0e zWxQ{FdiiZ+B26QE+SFe^_;?`f>hJtNa^ydKH}4uP6~2{JA}{rw{|r|$mLwOdDT&)o zzB-F48qcS}gwJT)K|!vDB4nb!9987qtZ4jtzsB?A5XCnyepw;zI)2P9b4ZQzvee+k zVkk=v$B{pigOzSdj%don@Jw5XwBB)H+L7bqo57Gm^4Cd-OnJhma_1!0cFZkq370TO znF5esYJkRIzykGA(i|(;TR5pR?BjX-y-K>p>n|^Dw65^SZx)|cwXLr~; z7+oBo3Q`yPpd4Ho?O6yfKe7oLpB#@ypMWf$*EENfGjw;A@U-TPq=1HT)3P4#4yyQWjh-32I`~sMmfk!4_<`63T~X- z&1$=Sd?zzet+$FjQ0@d;ur3kb#xlM3-+u$KVjzEC3}`lxHyeC&QR|-^hEpNqGib=t z{zi}a%8!-7BB&$sXD*T&f=+W|`wBva0vPFazI}bV%J4?wC}iAY*2V>oZJT8G*EOzI zb*C@woM2Vb$kC*oZ8z~M=zg7+?QMeC9qhbyomOFZ@o&b2NM z&Gxcat6d`1RKJ$@dI(zEO&Hjg+Wr;mBMhy{eUl|MYn}Pk(h#Cz*atNl-cmb$v|>Qo z+fb}#nYfkBAaixi>fw9$wDnXw4B?`0VnGA8kPS<{E-*qBu=)yBTkHcoy!f&WVrT^387~Qezw2PZmPS@gv3NPVSWQMLKy)HX>aq zCRw|ZuXrnVZ9^1y8uB}STDOfy3lXdliJ^jFB+T;rE*Al*d9@J zQBQYw%NA}U32!?cTJqpvcNnJ~hv|;G{c5xJQ&1Uw1;q%9GGe`-VyYccvxZsX_DzS> zg|VM_dH2BrypHxVpr}!6dvFX-_1r*JB}TP&MRF>qT^1bjVddM+&G(`h$MyZg3^8yk z!*HhV!{cGBi%&)yHfyW=l&SCM(fCu$1AE$(AugiL40lAm&a9DNX(8r=8uy84R(!_s zQ@ZVtZH9@sp4;8H;5W??pBUNOBux-d#c?`B`B|Lo`2=pXxh2EaI`p!(aR= z?*7tO_Wn@>qPy&)MRSK)Be=|I3%W&h`?SKijWukaeb@GaB{6V!wv6^h&Goy7D5xjcvtt}wc zVkd(>rKQN`IJ>|9QZac0TVHEJyh#xRgfXxlL=c5TrbCzXJ+5vlTiD-y(NyYFV6@!y z<9^XQBm+Kv2>Bxn9PL>@H5e)%fmzL~WHX>{r$!^8j%JN9K^rBbn;`s9x#RJjja;?q zy{;TJWz*h4K7YLq?Qk=YuBOZjmu817f6F1$bX~Y9?2(@OeS`FtI#Pbs1SULy?Khd{ z9_tR;tVu}nbm_*PDcdKw48F@8tjT|NnFlg&Lh8h87v0D%g~yQa`CuysYsza~3j>yg z0T@mOpH>Hmzmy7ks(|s7&p^<3OLzrA9G;h}a6y*+ex3}B=K!IKqs&M_$CNIQo+49O zx#dosk>}rHax~Z`!)n74(Yq{CiX1mbby+we(uUN{lH?BJ%5DN}&l@FWLgG3Hm|}%= znKg|@<**z)W%)q+q`7`DePQ1#P{};JUXT?f9H<4BMKrmPz@v*XY&nKN#zYG+%X0c( zIy!=Pw`Ma|00L(=fmP`@L-)5#Y*X;~TtQc8)T1qGGn{@JIR&6}kF+V4Y5c@&tXHWd z2rs9~g8J#-gwdqDRx!>ILrxs1o=zUgSf38#^nwv1GKGP@nuzGfUdfGQ%f7{o+797R z7aE^U@5HzF#_sf`_bFr7J?L$QXHWx7jiE5G>3tP+Nq#Mjc@3#Dy9?$XHvOf-(&*)7 z(kt(`neE(mH!_Kk7lEB`yAx->`l;krCOLU1L70h1;Np2qH9qCjo-QuTrZ^%tH)@c% zH$6=0+-g&iAyaLZ49~^+N9;mtr^e~2n>8jO;|_4(O6nc@0mA1l27XZFo8Zwx2(*3l z);#3WXdHZNPd}#0(;WFSZLnM0?{=A7xLS+1CFDrYI6QWVa;fRmpt-ir_|q}|B?A8G zh&n&>6)(d3%|9Ujce3|i`=^w%3GjcNp8ktuul;|Lz4p!^<@-O$-h=;_WUrm06YBq- z?EUve{6EOvN?pYL1qfo%VebLTrn^@)BYRYD*8c*V5kXz~=7!6&Z*`V$SQ#N_mUYk@ zbp=I@M70uW3nISomn=}cx2&xNGdI+s?JainYc+3b^qA396hOw&QtA$H*)>DE83mc^ z@8_xsxh;GLfW#jW(MaxrUF;Fj&9!^q{WQa#BE7<(zdpb4;AeA1X6KEgK+20osUSx0eIUbbN#c>aoAQRmY&qC zfoo`X-Ppa$?A~kFHpWEWW-YUZkaybSsIqfmj6%y%)=wiWeUk#?P3v$K1u^wD`aLlo z`L5*2l3Su#?~v7GB{}G&2_j%JwSH%D5Lpd5yI-Ab?1rjqn^!HO$&n3kLVMSe%i}$H z*}kewjr^)~;X5mVWSN96>|PcJ1=0h#;-Kpaa_gM#RA-)LUOqkNt;roB|Mc^9U|2DG z30QX7XjPvs8$xLrG63Vc!7)EsQcm1>*Nhk;K!^9Si71tk~@aD>2+e;%i=OAi3p$VtN} z0+#Ksxb1ZSN23$I=%$eS^u~-_h?GIwsU|ur@xH`!KwJD(Vz{x9rP?|zNL#m zn%tARqO{pEK*Dl%Yn2gX5{gJeC{FR0$O-aXE>?h*3TS}hsJ0PRmOsMDW6O#TV*Sly z4+=J}s*}jVER2v(SgRW_RCIQWxRVlc#$UVGJ#!qcUoBZCiBA*_it(p7l$A`jEKyDp z_9(bi@{Hd_IhcK!7&bD+^m~lDg=MNaR8M0VYm5Ledbzfj!CrrWss_iK-deLJ_fG|? zm&4XU=>rH5jPH%-~hV9yk=q4GX9urW4b>jJqeLK>it5Y6ItCMpJv@jF3UtUgCwY?|lJ=V|8w+z?u=ly}CmyK8W721dpa_t2k& zV<#2!wjei>6Fyg!LsmOXk!Q$l8KE2wfsB2b;Z$y@I|)j=mjxsYG`#h3m@I#-c5MXP zUqer>1&T)6C&EKp1*-fE+<;W*KU+GVD_#-5)i#}UhuVa9;qtdsWSSNY=L-RB^$Ts* z5bGndpyB0@%}dBZ|BS&oOfe*3WtW+DHS+n<4Ad*N%<#xpAHL=cM^kOw;rtH&lS2^~ z$k8Kw+bf5swg8J-lBqiwUp&1?BXQXsAQJ>d+h{_8guE_f1jqzaK(s7Rq?U!510LAT z-!)g^^TmvyZmICC-Q7X^tqb*DQAu56h4ok>Y9So00?7CEB_TCz%(P9Lv^|EcZ!Xw- zv;GkYfOmsddLoLpwwNke>0WuTa~+5x0F89T06>~*+B_VE36Ro5MOEDaoX{^x{kpVu zkuI=Y-&3DKA)S(t0c=b46gPaemV&nuQ4*taR|WD@8G`{+{4hQRf0DxqA6_99kuoP; z{rLF2)`X=Ub-vv*8pG@C*cR?eE52nmYh52KPAr>085gJh1O#+7_SPeHCA6u5OHhY#|;}#utrft8v532X^h(h#B3taxefN z_B0h&q>u3%$MG1jonhN1{222^3>+7vy(m`CPJmzFL4TzmSV_qt7l~^Bu5Ps9kV~xC zdf+#`=(_>g+E#E0!KgGk;FWIyet)f=K4MkW z#$|fH^0u3AEHC>sbP*&>&5X{EvfdYeaWd=oeg#Q$`qL}Z+bh*xDb2~`S_#gm?E59? z=YrejPM4Sd4!Y;v=VEc6)!KzL(?oZqrD7_5b~wLh){iy4W9ygk5RL z7eU(h`5q0UlJSKDs>ohvr5N3E^m8k)D`-}*;f3QjKh}1ugNva1_3Eai{Cu z1#pfiQME{eI&Z&A;7f9{w6(YS=3C6l0D%xoC#2VM72WbK0FaYc6@Xx5G6TEL1As{Z zc@`K3uw*en1Ar*(B!G?X=JTi+xxCzsN_f$iA-H~x75u?GE`k2Qz^GQR zffWe4ffq=9As_?)5S?}Zi@tH9@OhyrXwIw1D$L83@c8b0t3ffVFXHSz_s=*GtdvOU z9JsA1up$*i3&(KEbO7|~#S*gkwsZgh2>wFZdM$ZHLFti5zkyePulB3fXFvcb$Qkmn zzuPAdKf+7osuHY_2h<4s<<-y5fs<*_1_1y_?NMABJqrs+qy%pC2mw!^yec@lrvS=d zV=SYOIB$hho`CWjo7WNEOc03!ZOhq{81 zRu0{>Idp-@Bmz(zBJffGc`aB|@6Pm2k?$-kyY^!EjQ7u9ae2bW-~{v>AY@78@ys_+ z=OcI1j54Ms%Zt3?483J!Q#wW-PD;O^N6zA9%|;OhqcX%4;T$hC&t~5;h`kT5bSKLD zn~LZxR1r679c&?3%CCZo##7|^=?b#igSJWn9HJ+0+XkY`3|aNlBTgtRbN8r{Yvs`* zv9>ma4#=jiiVYP&f*jz8W>dmtQVvfcY{e4#2R=pD%JFm(pQl)*%yA~tm$%X7a{_A5Buvgig0pB(i4cp?brN`(=GbgyzMf#fI&lT?mk{9RGv_6Zy( zDq2Vn5X)0|T~SArebUnk1u!wHv(9;r2GQNJHs{f;~X>)Bqg-)_#AR{o$EuN zh?q{u_SI#7^pH9Ht=zJo0nZmf^{qfzu$G`JlSWo6;z`?xkyI5hQl|;@NstUof=vdr zlGgIgQ5UE?R>cPtb&tI7j4Tm+SAi4}Q%A@o7kVz1|G2FjE2`tk$bvi>$x1LL@S~C= zgQ_Qw0b}>h9Z=@cDjuWgLLRthv&P`a1w@VfZq5{yx1o;#c(2E?6TtJu3JDi5?waOcNkTd} z$Sey(B$aN z2%y-Vm@n!6K36=u*+S-9f0K0SV;Q|&oR?hp==8B?XY92{O+T3L1_yAuSVjj(azPXT zWXgf%!94l-zOGPkx9_{2S2}iIc^n~S@rM_{s#GBnC|0QxbRvgz18RM;RE;_}Ue-;z zXridUp0^^A@}fDEsW}Dcm(HChW6psS1RYot=K%xJshXnMy0=Z&}BEZoY{SEk2*n}?@^u!h(g{06uIXowxV{{F!q}P#1tJH)+ zt}K5%YzuAL-*;p;h)nrhxB%Z@8| z@|ZX`Oa;c*zCqU5nF6vyj)WvjFp#caZ)Q@|X|*a#Ju$buCs$@a08)I=HtY$bB0$TWUl#*7e4rVW#FL0(jdU%PyaehTyeW~p z`&a5H>j=-=UtYiAYH??h?y9SS64{D3@PORLme4b(VB`1I23AusvUiq1l4Wdi%>b!2 zd|lrUeYIBJTLsy|Uw&!_QH}1euTU^zGr_#<$*OpMf?-U@p#8S*+|=n&$cU8a^%EM*Ar$@nsN06VCH%^#)Ul^?S*TWdm<1pcib?X~ zchTUS0ahj8836Fezy>(|V|iRaECWw;4j`8l2aWiHx5@M6-g5AAamc?j85J#=BwRdK zG0dBgWAZst!m9kvL4w|oF_kd9wryf7T{I)VGNAltOI0TM#`ZT3-{UsxkT<#4n7-% z%-%Dj2IiWGE%jmVnRsgg5sm|oY8Z1am^n#%&x};)JBH1Gmmu=D>~m~!IkR#5XYIjM zCTG4Bgnb2Cg!*ns#j4t)@22iJu6&4Q=VO5R_3D`QnR&`Qdt z50K;eYqx_qaQEy0_ob53Sj4z?lvJ2PfBMK*o0&1i&viozuz#mVvH`T!80`mGK>Y7v>5DZJy4hs0Gm6ComA8 z-G1ET5lxlj6eB>EBw&&ZwFsJE`ycamxV_rIShC2{wv+vl^>BvGdFt_u*bl- z_GRB;Z=e?odN|!H!z+6fFoA631|n%CUJpAfjj-EC-IF3R!tsEB)jqSK=d}7AqK3UC z%H6`CTm>bP6CfFw16;R3%iW{``SaE+xrme{jV6I+8l-(<3YSOc^gpl!QZiBoCIB3Y zp)o53oi8|aD!7Gq;QcY_%IVE+`&-i$%oEgb}yh}(WM)1c2lz~RTc zoQTS#b^TM6$}{>q3Gl#IZ?f@+M~jM163p(McT+s^6w>59azbKC37tZRpJQsw7k{P0 zu3*VyI8|U--cP^$&|J_%rAo0_q1?Ag`;92p=;-)P(%7_h3MaC7X4pR{oMYCTAy-BK zPjlH~hN3LmY}a5HNFr>Xm|5?Y=hFDc4>?>jU3aTs4+07j4=kDh-YQQFgaf2}nQUN+ zECdwYJc1-YU`oX%&6t1*8juaj*r2$ZH$&k)ApX(AU7t~>XO(Qp%K5xL*sdUBQc$Zi zej6e7LP2uP`aGBSVPb#+xBc4p0WX2IiBmrG$jK7IyM)2aV9Dp#u3gVxzpkfcz8~H& zSKmIFQV3Tda#?ZGoQ&ZYnTyM=8PGyh!BdQqsR{NZ$>oEH4#Yz8pB1^@Zi3-_pgC%zzcbMWfpiPNY7UCVkweuQoflEC>+F=-d{u zVh*63Pp3#)lL(1<`FCKYX`p7ie^T^lt01;$fM-^=CuzDUmGS^lb}ehs z=b+E~Gv&svpN$<9KtESJxI&kR2B_^n?y%5K2el#n-p8~DqV!(&ITfW3zIfDLbErlxG|jF1g?AN_`IUJ}Q$3 z9-n~4Po}I9)3)YP!7XpqrZCoUH)A-B1+giFC>rGMip~MLfB4+AiaNfCihLfowJhpT!k30y+b!JGi9 zG!yivVtUydFHht1--FR~R7aecp@~RYlWds7pQjdx>QC7m@$x1|B7cu`{?(EZPS zf_w#|mR{WR>$h^R?DDIdIFAob@jsYboP2dUD&~*aYvPc1`K*h5O%Lnnl*Zt+(tb>)v)eQO}4^qu4UsY-*_>V z=_SOiEXSvPv+Fv?!=Cjra6QLUXX@81(4_Ka{o{Kb#}=6OC~9mWL?dAF5^_`>>Yevl zdrHm;NTEaR`5Aa^Z}GMK@-LI6;(kDn?6pfS)guXW$b5Ij$Sqf16JdhTM!)60VwN)z zwMvi35zk4)Q8@&%g0bEVfGM_Dk3R3)u4*MzL?ZMQa&oK)$V=zSW&k|Uo>#mQcU&tw z|FK7x zLIs~^;Vv-ditR6vX1$p}I>J+t2?^hoWhmZNCLhu=}r)h^huIgE(kT4UG%sg6YF7%BoYtO>tJM0+|iI);5 z=Gz08^&{hN3(M~qPZ?%R(Ax&*+eOml`nidO4!4Wx;=q40cQ-JDsyw{5Hyhli7neMQ zyA(1fMv8=>piJE@p?WE{|E1qxE)_9mJXkz$(}FJDj*~lGDJ+6f++%tzpW@P)0K(*PE9 zjS&X}K;_>sLx<=4y)ZlaFn7 ztbEJ%otjPraYK7zY-KEEyEZm+Za8yFG$4do`!X{UM&P72c8U%1z!2_a@>EkXIhUJ& zuFT1K{qDdgoY3`l=L7eO_MU#zMNJt`|NQZfchk108!>M=tCeO4OfBASG@KM@VL&)u z&IAb7SNp1$+^fNk?p6){Mo*Kn$Ee3)NfQhyG95d125M2lSn#%UN+m+w+zxqp#oLQw zc~KC=l_R{ay#B{l_2w$G75(Vcr2>;nv(4(SO*_#2P|PH~k(i2>rOc}Oiec_8+~bF5 zr^tl~+r{x8Tjiw_ z>DGjlNm53Mf*Cr}$dtE=PM2IVr6-}P*3ID(c&$h6CxZ)D_f;WYmJ|&qA@Z5JS$F`p zufq{oopzT*L4ZQ7D~@uvOw+Zpq|(U}Q;|mzWDrfCNBsV5CAL(7$aACfArZoL<2>c3 zVxpD;NOI>#eStsV0(@RC^TlukK7$lmDxX;=64Ge{#$wspEP-$X+4Rc!d5JL)Al25! zH?t03yi-JzcEh}K_)$)=>m>1vp!-|OfV{OttF?tUxT+X1ZR4DAJbClL^{K$J?~lt( z_$5QA)iM*E^SXHJlurlyJ5UOyg%S)^19R_vdEZO7M6Yz+e0Nzyth{YN!AP{(6H6~m z^t!l#B1Yn`=%b6ewmXfKpoiWQ&3bE-N-`hSgeyUm4d0@^pE-Vhw>BrX6f|^$*}byO znnBA^qx82ZpiMtf1~HbSW(hC{MIGF>1I1h4uBg*e=)3bvIQ)|B;*-c2W+b&;OPZ-q z0Ba2J;;`a&%C~?c@I-!Zifr_u6xX{-gB|8KPG^LUmS**P9)Y=w=1bQ~V~ON|64Oa0 zp&RBpe+IQoi7ge~MG@MVn$qdG?Ubt=924$79ZPSA6=e1{{8o~<^SM#eOQWWV819+= zlA`k9Wt*(M0RIThJeNbx#b4!`0E)VFtFIkP205dThz7q-* zYsCuXmBHgG(gB#M=ryPZjZ0m~Y$8s5QK^FqF%YeJK5=T>Xesq;?@zqQ8c;cYy&2q& zFffWsJ)`fw*a20MEOxZO#Y3p1ogJvNk5MV3C4(^c68JaNRO9FdN>7hVtu{(H| zNI$VRPJc>-pi0P2TWSK!VKz1ODGVYk3rl4%RyB!wDNBw)9-=i zTC3VB7mnISxNI2Hp#>NuH3Qk=MCkV%BDTM^bK08t2;Qzmh%NCBqgr^p%Ku_;q<54Y zFMQd5 z(TZHlreEJ^ckLZ573_(viM*&Y4c3N-*IMHam`INMOCw{c*Vel0dCkvvIKv12wtcht*|K$uCauiGK`Lh@I>Q~7 zq-uBJ{!--768M~d)1Ow3J_Ig+5ACqq?%(OYaND6o?`}S5XW(w;U4;tkVI8b+T?^TLj=nW3*nxEA6Ed-#;Oev8f8&#ngK)+8)@Bmm zx)%}x)EApO?Iv9A3qGY*U!de`q%SvaE!ZHuYSge@j`P@(AG>}&*iLcK&PTmr{KAnK zlHyhI4^;}*-tv=U-@Ggtk||Fh200 z=!1r@WODvOuXXd#(y+xGzkde#d(W#|n`;}ZTNaYE;0eHs@(0&8y`Rhwjo;sou`DZB zCFV$B zlwW&pkhagzxD=y}%e>{Bga8kk0sF2<>U^sNWWm_tUk%Y&a`XPOkWk?hqifNZUnP|4bL_>U9T zu(e3eg53|r9q2_(YUS@sc3VLU$%WD{uwIavS8rSje`aoOedm{Q)e?pi;%skVE#*fa zRic^k$qdr{zABJ*cQley_sK6Arq2YYg&->0$kblt=Wje*FPAY4`Y&L{X!8=hpN-46k9B#<~ZGJcCTy|@8lN;fLmPvgP zYqwTc{u}Plf;a0!t=&8~_&hrO5YFe~{k;3;KfP_z*6Q#MHp@yJ9#x&};sh5ArZV7p zC*eISd3&;gM9<>UF)5dg;g?zdbgwLSYDZ9<{mws7hG3Dx+tU6%7*Z6g}t5vY-FqB^)}o?PZ6 z*|PbI6>IDWSuD02wu26;?;E(1m&5P_-ZQZ5M~$(4S{4ivh`0 zk33f%l`n~=E2jDZVb(YM#{>mgCYCCMp(7jt*f--TV&z)5-n^8_3Bcl`Ec)@frMPzo zz$Pi?t-m-FH0A|6XBZiXw#<;b#o-bxxB4F!8ZiW#6Izd=|mrh%LA;Urn$GB@w_ zQbPF0v2V533V@ngu$a4dTMbP>lcsR6QFyugNGZ=ZYqfLV2!N$Xc@ug)=k$wLCg}70Dyei)VN}-`(rElPs8Z&IG z{lsD+%~ty_(|y;T{Cj|p%faI?0R3@Hp&%Qy8+C&fhnoF6`eZm$_>XFUo@#$3e&3=b%FRog#QqGsFb??wa!R1Gm!xBNqO>fP?b@cmiRNzd?)d zk2h3zj}glw{xK>dIvXKCc-ZxJ+OCDWO<$&Ty)Swnu=l*te|f*&s|#OYqI0{ojSVfF z-kn2TZ$9MhmHjwM@0F5rCKgp;cL;0oYj(Lt?XfT4vxgjRJhdp)9*qE<0KXgAZEAUR zgL&ik!b4H|e_k*!)&nb6IP1fWQP!ssi{|%lqrkWA=m+N;U*2b@IVJ5Y`=Dp%)RG!g zq5USc^@CIE6N{2JMlYXa|NFjnojGvh_cf>tqV4dzxa0ma9fiGk6yWc_meFkBt z&quK1Xbzw4EO}pUO(_ovD&=7J_x%o z;2`ia5rN|uql+dc0w6=M%akO2BF*gT#)5ek`Z^5_}GF&fz|*VONbWW!8m$2G_Y}sda(7=Fc7Szr zDMJE=PtZ>*nV43;8YKi*qQ#!oVr6wi9vYmN3J*d|i)ww9=jN5W1!&56h|RYhwK2Cq zhrpnsEz$1_8)x2Et76nn&MPB4W zXowy4BK2TNFG$;jH24uGJ=HAP(49*N8=kV74G6+Oc!ePfwfyS*+77gJ*0`_DlHR;B zP_*S6I-ImQXw8=nwIo3IJhsF#ju%`=*UM4sd5f$aw^1N$$Fb;ru`?ls?W4+7)L_45 zgw0yPrMWHAVy8_p)o?+}O4PsDpgSDw(Kpc4~nv;DgxH3D`F z=J--XTb64FhM8T0L=Dl+wq;%UNzA-Ml^{30wkvRel9!7KAz4R;v#A11M&Lm8VQDBX zvznBvW~r%@UWJPc>YW0a752c*OfXsk6H?8`_|krDKEV2jvUA3he!cI}l6eN-G93yc z;l+{tx5~V=hbpvRGni^;%`K);e&*)$g}v;`CtIBZUHokyW-1uvZ8mE{tjP(w{fsBj#P;3$+5e}iY#)6w;6B=+-Eo?99PM=XO z5&i3!$Pgae$l#M2-+CQE9=U9;uCd9t{L<@naJ1Rs3}!667C^L9$|`P}yP&Q$SK1L( z_WljdpKlzTif);u2Rt}Hgw~ZS>%_wrc55?UCIy?Fj(fMiD(72S#lNHGzdvJ1C+a(l zC~zfIIlKUp7^kc6b!pDVqA}RhRY8)nzxhM0QX3uF@VtWJT76C$+PY3zr>$g&j#y3c&aP!c$|sJK-nRE}}%~5!KP`yQ#u1ZPsdxVOH zwU-5H^Vc(S?Js*Ryb*s^z~b`Z8xQ-2@RrDU5=F5w)n@@3KJUHEp`D?^P>C8?u@pA6QJZQwL+#X+G7|+b6Wglzw>a3`;_xndqXI#s@UZc3tdK9^*WB z?Qz|F;Gwzeo}-_R?gO!3Ia?y>0s2R9SwdW>fEyMpS;B({N@z#pDU%y6>iZ0W$|}D7 z@DucZCt4i-C(-g>j*wufI;{pt6Z zwsx5~H-$Dr|Ngh?AiG=kye_T!V|dSl-M=wNV~<~bIh#SJzX+eHOUd6TjmAIUULUG^ z%+YcAzBD^G7ZBD_diuu5Q$Lpc!#jtH&JQNMOy;!pFVlGLZ;xDaAMJFSk8}#n`fG*0 zN_fVOuF*VwzVPX?-RRfrhVjdn<9`eb;j&~}%d`7dXWCZdPj=4K60blte${uKKh*^}{U*{bbnaal)CoJ(d^0zrv2ML-kJ=EJh6xK zyGBkK*=l?`=XMYBy1H{mICR5k+F7^k_{oCOiX-%(5uVthBE5kio!0z#YwfJEE%)M4 z?T)xdw_p?vw95{TnU2xURMJ0hUS8m9eb(%?-)&}+d(%FbL}q{b`a5o&`-c*I4Sle- z^5kGl=*lU_&a7)cjMI*KI-X@+w%LSY#s8&I!gGjLuckQ zev7YH3AjJ`PV3NPpL%NK%&XespJq?~Q6El!`uS}@ncA6_ggrG!A3Cf|-+iV%olU{6 z)=*v~ou7O6o7Utj<3ioInda}d9uEV5I-94~crf6JU68VEIO5o@EyBsmt}6@4Iji)$ z?H=g^>OEr*7OxZBj*Nz#J`Jr;;y!=w^hAkr+kIm5Q^A#{<$}~D>w~M(i;T9x#$uCO zgT5aJeLg$AsN21oLX5PXPxy@;bzk>Y!mHZxI}j`})c9j?kPo-8A?m^xgH#FmrfL7Z zsvv`PB+Zm-qrQUnze84eXhBs^I2CkowxIRHL(}YwyRg!b$V+C%-1D1a=yNx^)iuT6 zC(>LYWY5pT--k2r3@SV9E_NpEK6!DzW=M4=SxP(iAU+miNc=l#q{rm;eUJS1QlI*e z(6N2Yy>?o&8wXCb-FS(7qIoFBKk6sF@Z)`;KJaDUJF9c-W9{m^#*&B=MYV886wTcTgEr}TRU52BX? zjtu0{AEC0S#%JFh*s$@;{}fdE_O8~Yobr~&sbXuyE7%Wj_Pw-4-P6kdOK$(-K{9(I zxrX5=JFOQVJh(Y+G=u|R!8-P%y>qFXV-Earx0bo@yW`8_J!<`;uGbSimS0a67Pn3O zU7Sqa%Dd%@38=pBc-!*ME-Qb#KnwlH_RWca6J_Jqx`I#hzo*k$lxlTH&y2F;=C)#+ ziT2-g?M$WZyL{^Y*>|z);j`8|x32w~hPdxG;_NZV`g0BDH=*P$cYmTCq5m}IZRsPW zwoN-Y4kG*?QFb3QkJw!TGhy}G$mn|*2d4#!k^t^uf+D3*FUy>dfX$tC#2M*VnoV1;&Vc?&T%O=31BvFtuzneNBmZH zbM%<=`yIdT-27wzJqTZ*>zTY3pk=EuW-Q$IhgLX*K+&_*dAay!{)Fv@l|zWBH1CfK z+qa+ps)i2o$qJ5dbHmm@Dy)rI8|vKbF;JXnb<(p^;&ubmiLlZk1THv>(*}QTyjDJB z(cqi{vAJP#Y0qwtJj(P-s9MiX&pqGE08Fhzz>Q^X4VCd;OeN~H9rjLr@K8q#Iap4NUQbu=gWfE z+74~U;{`un+a2TO)#CNoZ*#cOy8Q3OU}5J$XpZ(-6@1`T$k&}n6{}6}d_#V*3#_OK z_}w^YSK9Y0!A=?`^#;?0tk~-7hC};5lCS@nZW6XO7o+oY=y5gHKZSexZO*!8;rs0K zGf%yx-`TfMH}b(%*rtZ-OWyyjxa*FRs#yAnC^9no6fhv*%uddC?xZ_8@8rBYJ9&1( zot%RU%VU8jDySffAc{y>5fxBYKS2=@L<9*21O!9@K|sPjML-Dx-(3_1@tk+wKi_x% z>QlF?x=;77s;j!rsqSiA|J{-E+a7#&jYLK2JXKhTJk+zkb}Mvz|C8w1>gRrV{jm+U z?+-oG+R|ovbU*pw^GCZU9jGT{*ssjv7ET^8{OIP*!b$e;)-7xMsqc5d0B=w&?`%?# z86%&fjhZi=&DlR~%!KNvmu8q}i@ws&AHSawAKf)+-2FfI zJn|MXnAVndpP10ST{nn3;PZ3OXDV13o}4^z;ydzbbL-dh5W8)Y?*@DiKB_! zH=X_db+fL2`}!BCpY=1V^2>AedtYbY zA$fYx&VCr_x3aCMiA(6=^zgUI-Zhr7eZO6bH4i%b)Hj&ZRoPurcMnpJBt2AIF!aY$ z?Sl{AmL9Rx*fI1Y(V;C97S1{|ea?@ahpbNy898^)_UYpXY;AJ)j9xwzS|}MfX4TQd z2R}KvYndc_^hovDHOKLX*WJw2j6bvHgAdx?$Q)N?zALYtFu&g{V)^}1(~?kr>R!it z@7;6i?e~dypBx`oKv*v|+xd9++Va|e?6uF`cX-gwclrc3y59>#E_fe#IP6Vm=U6+Y zEIKK?HS*;?sPW|d4U2x+{nV0oUpg<7X}Ar(<*Nn_yEOcc+U#Qs_W3TZ#q*K6JNKV? zU02fm`{1UDgQpo+Z}7gFE}94r?DTv+a_!^gQ1`S&Hs{_Go{bMzew{ac>A`ge`X9Y` zWd4}PKm2&a*InH|IEI}2GVo~SE#<}YoYg-XFV8%)D4ls=Kv!GGBU41(u30QYb=_fF z;)Qqqu~L{jG!LS_xTKqWd-C>|Y9slL46}9KT{JPtG z3>MtWtd1sHyKY+5^Xahl}lEC}bYhNptKRKqJ$+e#QS$yv) z(Jt^7-bQ%t%jRt}rYv*(u+e23O1t}i=5M+5=KY;7wPQYbW>EVF>6^vG9){YKee6W{ zU1(3&OXCRdPB(nH;lP`U$r@jE>aZVPZQsQ50z&$Uz7u`2*9?*>u@5UcFtEI1M<3k9 zV{Kh`v1q5qcibP_IQ(#Tw`@=3k!fpR5qz%tc191ddRzO}?T3y%Fnnp{=u<7wr3J70 zr=ERwMmyc}>Sg-M^UrF>9GID#Tb#8v=x_czt9m!pkwOv!T)dqJTTyl8v;L4>bx2~K-_$+kq zr22=C9~!oKSzEusn~!XGbmeXHFZX;v#$9exy|czgoZvn@>eS9JMk+do&TU!TJdcyx zGisNF_QTFo!lk~Z$-nG<3wh^Y74g!zNy~qpGi=aD1Nr%L-Jflo?f!+aWxz$_h_N{} zHSu7eW7_`DrY^?L9mi+CvbgUoaODfABU>IA7*MU4dQ#_@0Lkj%Jv+W=8R$OdEN!PU z0b2dU)2+*_D^B7bxc5wD(u%il7hEEry`1XN@fUQB9Czlfo8hS|_BQNPZir6kRHwhc zaJ;_bmL|$KE73iDJHEK79zhFv(e@cf&1YCm($o^|iZ1#P0ed+vS_VvjH> zY&RWQ-G2JxsS!P9Q|`_I+gE&cq5t9f6Qe%fJbCSpCCaC3ITN}T9uU4ZbL(&o<$3g$ z^;pfJ5Bt2n_`wkds_ezR)7AT*_FSHRl*{#`|7D!}&HjzI|C9Lrv-@!8-x%BQoMzki zOIe1~J^IFaZF)kbJ3VnL`0k#6?l}9^upzq3D4@^S#lsKZ7}N`|iAR4ALH!t((xo;S zAf5(}72`05W%jlF-V9zXQNb7dQJ?}6Vp!^8u2^xEA~6`lz8dr2@D@FUNP-K=S_;Dk zuEhPP@BqTb5V%rn>1lSlM|SEW~nKTMwt!xti)%9 z@d16j!jFjxWL+r?CWJ&B>@qaPY|b>9;}wS`L@U;T6DZ43IWcIZ>%s(M#pjC}j3zWn z%;$i#aN3@hQfN9Z-@xJJ>9EjBQvs1GB?X1T+KAC#aGPl!#N0I(gnU1nLJ<`p2dyOu zRACRYsS$6p!ijTq$k1>hUaeK&NWQn#dxvrbMZFCk7pahPmB{}8K{WW^AzIZ?sUV1N zE=s5wP0pXSDOw7Cj!fOxG0HOZY7 zcMHX%*YI@Bk!*~|5VMqaf6d9LB%MODK%c3I;W)7cjiRJ#{(u*!kA^4#ydO>(!`QM< zi1Ue~LW$hzwkm|_kla|KB=oVMxuURh>On%4B2qG?K{c80G%?U9Z-B=1`UnCz=O)M# z)=Uv@B`Jth8%T|s{H#bQBd10=HZM#f;1n63wMMnb8_ITzTLjkPgbFsNM5Fk4Zn+{( z>It5(6JlB|kubp>2$4K=qB5I^hD!o~rlci!*;q3!#4D7<4HBNJff{Iu)f$bdKrZ~rrqsHOjWQLOh!YJ;6+e>}no?AWG8+u~=v2Me9j4fV+`Ou(3I=6F zKP?M#9T}{E#felBhzNl!MhNGcye-B|Ba_u&a^b450M4>n%T-nmf?Vtjo*!YAlUixB zgPl_aoI<0u4)bH7s8LH2S*&Q3E=TvIavX~Qu}=-WB&8-H4&fhC4W(a_`v zMIb2$(;Mx!h&NuahCIqVEe&|WJ|8_s4Qtg7Gboc9SrCn2Oyq#S)yiH?=+#OAm;I+! z_FnW}z4!b-JZHH7omK{b)(X#hMJtohQUdpzRw{7h5+fuatL@Zcx{O8%nRQizG6zY; zF{wdr7jk_Tnb2DYGp=m9Mx{{oMTp9dnx!xu+l)66^l&L#$L1-xhH^d|FNdooL`0U% z1H1rB#9}7JycVJy4l(==1t*^1rgUl+*^ntgbzexqPpV4w#xxa(*wPkSJeL$ZGg8p0 z5TQ}9f$4GO1-43A+gum9MLbiKk|@{c?iei!Y29T)iXpV>G{TJ6UQfMMQp34!ZSE@Hfm#(2;y2Gt`#v8g=T5CLTfV7#Uz^}#L=WH&)@5lTtP^tho}CKbaO5}&Kkr3HTrkKQfmMFNM< z{}Ucpt7UN^=uhG`35ToKeV2}5{6lBqDadQHtnt4?JPl!{JiSggsB?BpgiiY!nSi=mK9Bw&** z)}YUUD3>}~XXZ=|B>}etvzrK2rp8Mk2G~t;W2(aAGA+VLoi7sz3;b4x2szm8QM1d} zWY%iQkXAvWvh&F>6>ch6sbVV0&7mdp46PQfc?e=v5nr!>)hgB6%4A@fSzWly*J(5) zG%9W?nz4{6g44R`3O6>8fqae85?`y82xA4Qm7kGVAcx$K6EwujB(@AFB*bK**wM_7 zHfuDtqkRM6Y z7z%NCBpk=EH1I>|80^%kFd&bIVfR7}$wLMI@FK3s)1X;u#OtV~iv>-j24lz?5nCt} z0&GyoW&<1$q+H1|#p^M+f*~tom0~nf!)VggS~{0QNa|ufA1TB!945fVB#IS`tC)*a z(p3z|;{7f;{pIc$N>3lZh$O=0u+GF5rPa4 z(#uke-#8&2hX+v5y~w}n4_)KoUz@h8BCBCa$Ez4W2K>!;>2;i(nBP{SH$$c_){zt$ z2Xn2okrgOT!4=p3)j;G z{2OR|PzWIkeO*5RPbj>B#%JHaD?l7jB-Xf&7Xkq8U*`t_g1@8jk;S{7m(54a)(tcW z!PxcvKoGcr7X&#s%moB_$h!Z97vdmB@~^ZT$KU`+==DdxS|yT3@P-r|M6+D!b{N?t z1n(NZB#{7tIENz?#v+jf2aZP*Ae`VuA~3*@a$`V5_MdwM5ey)vG*YQu0RUUTK@$jC ITO;~^0Y>HtJOBUy literal 0 HcmV?d00001 diff --git a/src/modules/oldLibrary/Material/references/Dixon 2007.pdf b/src/modules/oldLibrary/Material/references/Dixon 2007.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2ef7e4bf8aa707fd15a74f9308954906dc268e28 GIT binary patch literal 119934 zcmeFYRd8HQmn|sE!V+0%F*CDD%*-lb2}@FmnVA`Ek;Tklk;TlG#mvmiWRX4JfBW|B zdt>^c=V2!1q0duBMxHovR_xrl*4jI1)TCrsI9Ry>G`o9Ka{vx?xcdJYR{y~Qpbq~W{ht3i}halWXRW(3z573^SITe-j;>x}nTv<oT04&Gz@{N3?-yq=k*iewkAf?UQtye%Ubdo1E@n**0MZ>z5$PhmDtl z^-I1RO9%zERS^iMN1PRwUF;iqTjT+ZDlC4tSuk-PN2rn*@+b#w~627S`2< zUtc`6@lsib`HPyGS*s()3)Bfvlxe-h>M*b?fn?LQJHtEWB_OKW4M>r>efFZ)X0Y*; z>O=`3Ogeb3pS=C#3>lG($)`A10sJJ$Qk(h$VlBzCHY-;L_Y~&m6apnos)}QnHu3H^ zvS|nY#tYcpC69$})aEc~2QPyf2`l?}&t{zfs+ZH!|oHFyuxQ&hVZ8~p; zYlnc>B` zI4q#{Y*rwRF+iuV3K7mZYW;=we9wowH$r^Qem6kP!Z~kr= zG~-Kub9ekP1RO0Q@;B3n>J6PK?G#vy-1VpQj5bGT{c@greV2NEw(A63JfN^0CC7pJ z?(A6x%%<21UUCQXt8<@b?n86P#>8&oLaT3Wh)yyIelWRYXD*1&f`6$_Lt1SodDO^O zsT43q;QHZxu`$o9Ud-Xm6?49~){Z(Iy;7TA4jh^#OR3x~13o`e>-_}*-3tD*ESwjld!YbP$G{GAD3-J-!c8eZGP={rBN@zLRm;( z$Cw{p_aVtOTts(R>y9M)^?5hZ-7n4lMxS4B+nASIlk*_txPm#E^s#u?DbvfSd>|)9 zwX}i|0%Ad#M$>c(BJ&A!Uj=-ZR2D!V-d~xAWf~|Ac;{9pQmuxqV8}0-R_PR*53T}# zaLy^OE|U1*=j)uA@R=^Sh_@qdqXf{x>{+5pW*iV zLa(BgJleOr)n3IYB8uY6HL9)BglWBbdA2XSp{m)Qn|fCR=1xmCT_E z29y@Z1f9^ue->G>n1NSW96~QNoAY)vrj8GG#S~bYGAc8Q(JJR4+sa}FbgM;8&>Q20 zJm?Pu9EL>L)Jhuuj2aatrExuCP(aZrg3KtPE1D1noOhqGBL#C4>J0W4*i*AFZ zOr*y-=nxhdhGH5{e@Mp*w*(L(cBwAlu1>@zqMVO{X)(0AYY%sUpUc%>8)1*4O#` zLdF5X;`TT<4Ux6JOl!W9&?cxwT%v^MvJ;x%=9ffm47NWFk&?g6g{<;FV9#4u(DD2r zCSMKD)y5*)F1aRc-AsLgs{^5vN}M970ns$D)eI%?5QVoot_XcI_$+1Ov9Z@KR2AdQ znd8bF6ijocCk&M1%t=%6pH>G=jNt7H)_fl0tbSE+5&Ga+gg0qg3u8i|kw2{8`aOjx zl!$v^%;#V}b56k{hJCErIl&D&lOp7pJQvxi2Dlb0dD)J`IQGo1I4syDF>jExJdprP zgOwtX&p#D6YeMj1eMu|#Sd|R=^AJ>2M-LOUb)G)hBIy8*?NsqsAt5wbep0>f}X^O{Ku}TbffJX&#O%(V?~RFI^YdV-BJ4c!|6Z z)^n4~sI+q41EggW*h{Sv0{dZwyeV+Y)&Js#%j6gkRxj*&xPF)57q_K4r-HD@+@k88 zX#eY{8`LZxk~pB!a>eGSc3`Vb>=~F*=gtzglym!z>6tqzovS%a2d?@vt1(=VbFrDu z_c}1=?a3M$d4U;NgzHB-7SB`Qd{j9>fI}r{rb4fRA{Jzk;N`5i5Qgx2`a8Vn)9z|> z1t{0vZ}-HbNn3-t=g&A6!tW<0V>H}Gy8VxT*gp0MVpGcu$x3T5v<9V3!0+=OGV zDV#$8Oq#F74P+^4d{K2$pF5I^Qw<*6HT8>;R^PDyW~0k~RX2(}0kckcgVXL%r!tkv z;kOWGq4|f7`4amLrY2A&PP-tKM7ovNn{g%@@);C?j12?y#D+hHv6;L-u-HpMig9bUXs5MdL_$yjDu)L*78r5heV_kPUD%@6ffP0gRVbU z7A9e7)D@Uv>27~S`7^v3`Io!H{e%9ef)!Zat^@NrZC3e`Y5!|qKlND1cbs=};je;n zhMT6H#kcDuN3Mv^#)#3fOjwLmufW0O?7#eY-pB#pophiGFViTT+5H?w z?%B25b+E+VL>tlz#$0H2}lRwfq^bKCA!daALA`L!d z*i;sTm9sFQkAS@u%^&9l-8`$CQVWw7UY#ObcnpweP2)=xB0SxQGVBS(PvL97{~^qS z`No&~xpaX2)C#F6wH;HNRMIT1#|Y!A<98X1tXnlFUmk~Nv}zAmV5io!Nx@$@e3&K8 z+WP;yeB%KAhklcEv~zR;{bT$>$vOD{nbu&FgIZf!xsd~T+5S!2>9dK0B<1CSJpWVP z{clpwkWI(h{2w2gho4Qt+RarB>LTfA@8swJb@=D~f7gLLK=%J71A&5I172k=9s_nN zGg=K{O*04!L>^+N&tq%rqU6fVE@%$4v}0mt6p>V8HKb)%1=%=ADJfCADC)T=Q5v{N z8UPfzxw%Y*w1KSroGc;=)T&w{U^!K0J!w`JE;kV!R&gCIIw3^`FuM+yq9Usb4XXv4 zt(v=(t^>D|C>Mvgh=Un`Q^J_Vz>yVb&nF;2sb|Nit>7d_C&Vi$4>6OKbr!M~HZ)S? zwGw1hWahHd5H(WNwKLGBl$0@4Vzv;sFjl3c1lY@q)5@{|9rc;b1Z`C;fO@8`j1JN? zF067=+#2qd6l$g{Oq}#u?o?Vb5lG#zlQpiDC z#tz5=uvVtiWwaHN1PegG%(5yH^ftochSXyGh6-Ri7I8fbIw>i8khQt9yt=g##GIFk zPlM6O!Cb@890cT&F_Kl$1L)f53K(e98d#c8nF&ehxrix>TH0$G8}SKgYg(8)QBvvH z2q}TA92}h;otX`QX8g25Y_vwooNTJhwwe+O+;RXWH8)BjRz)r`WqF7ZH@%j=x|o9k zr>ME4y^FLmi=Ldmk)r^Oi>ZSN$c4wnUYed)&qPX*%3M-QOr6$5luC#aU@9q~L@i+= zC@LcCX059xDh>j18B)80Ii=}od35EC_@&uZB!Im7bW$#S!e*3|ApU^=#E#(k|1z9; zdHMd2aOSh%cU9q_vXbIrGB&Z7W#D09voNxwV6~70Q=79;I9Rd?+A!H#7%M_Vl^mtC zq-e$HM8&y<%SxZe9ARUl~i_wNp56ow&Qu@g1}gz4X&nJm5hf~EMrunjb{!#FCqsG#s62#893aTbDrjM=2{KgH zbJtO#)VGH~^+dtU40-}!7qGr6H?<)PJFhYavx0-ZfQg_P505BF(ScISkcSpR%PwL~ zFA9)l07*e;C4nxs<{Ye2swyC5DK~BrdJz#(GoS;#wl*K7sh*aZuDl)4)JB00%Bcbo zqL-9s5Oh+OcVje_mR1G;g*l|v>9~Om{8IK1M{Pa+85O6VT4jA8C9SqB zHLESPxec#5vw;)6jtw1~t&^FHri`?MHk27+V(cPrX{>4H%5EvI4}ch$u;|hAN*TIS zF|k|7>L_a3NK-qyLX4Q$xb@xW_3hLss8sdEP3TkwO$;@_ZYG*03<@?vKnf!_kh-)u z6$5}>UD2Mx#t6b?s$iz4B*)4kPtR#)X>6}(>S9PCFC$^9N5kSEZzy42{N#n{YrAI?+z@cfbVCBNY&8o}~apx7`<9FaSQ5WC_sF^B(z?w?Z()2)SF*-&L zdrMO0P{NVg-G$TDl~Kinm4$-UR@T^=S5``j4q&e6 zs6+u&giuLqGmB|c7}x;8GNw+v($YfwW)8wCyf#A0Ky^`lDn3ecXF3iMb_WYVdRjqs zEnZVCDLMu-F#`ZUi@AZ6xUd$Ya6+6a>)=gDG`D5~|vaGRh3x%%T#8%o;+LrfMp}Q~*_b zc|{?JfPo{B$=Xqsg+k{)3mGoH{|K3XuN{;BtH7-BZ}nu!e`?8gj+Sf+n&h0E|6^K4 zUQ$Uw+QGun%-xlo>)+6ABLo15f~5hVVyGoZ zi|HwfefowN6-Ay!^b7BU9wogv{E%>YtBGlxEoBK7PesO@S9+y2Z8D?n&x)Fw_M>&z zzuiw&cUyR|)Ham$y5HO6+6LwzkDPSA9XHcKI#wrp2ATm1M8cBm=|E~x_Jb<9jlVTG z(bBu7>TObP64aI0(UouviBeM07O|$%7(=#$12&QKlU45m;=U3KVUx&gw4G@QSRdu{ zi^Xme>d4=siUwshR7#UPM^xtxM$=*nAJuA$D`tsKJx&Qum$-rPNbyXW7MYuw(%`Vv z2JP@gri+u+j>f=mZ6mAZRM;D|cqhlFIA?FHElC}t{s+jnl+T#YJcfuHZW|5B+_c^* zjI&$|Yc)%ik#6{1s>X(*Vm+FHgC^bL?R^^~^X5|{S`jV-{t`f-8TY8xrO$U32&(^@n= zV?RUTRpBMF_pwNyl*_sCv(t^}8OcSR{lK!baRkoln2KnIw?o2M8T=ANW%zN(P)ju< z3v(i%8#7CX--Bk!go6nM&T=!Urc(z6Oqb5({6Il*Gb3*2AVFfI#hNHl`{!>~lHT3U zw1i-SR_~{)U!AXE!g?5xK|fBw01~wbiqfz3p+S940)qbEQ;^1l_nj?VF+aRcsu^O5 z;~NQa69ZifwBdrF%db`{x26^~a$hGPeYsC1ed#e3>we?yN&@?P68x7OPvY(fO~Kd1 z>*Kotqels<{=nmlUwLuO^Iga7acjOM+Wu7Yk)vN(OeTZIOA)30nWZ!wK}5<5DH;Z3 zik9b|6{O}ho@5uFdaqN9WNJ?qtLh#jbKi{^P|~Pc?7Ax7>0?iu?q_osRD0iOTSdA$ z4nn$cM-wDc!`7-^>tlBg&#ps0Npv$ZtXby@I)u~`35 z8))wATcz-*MW5Nt#9+I9`?TX|CU>8>*h%1j@S)X+L8OuEh}{=hM#&YU*9fqjj8zhO zL}Ln7`t#vRZW#30Bkcmkj2EsZR`Z7y8s=d29^0f4#3vL{ZD~?7dNqqtGP7$LH?jQc z3j(T5_f5d-O_?H^y`7WoaOrEz=%2z%bXL)xJr5%z)06#+ljsWPn4s!1-_SPwo^nn9 zT1H#Nn2txqs)~BDncPbuZU6e<3!~ZY!?zIaz=6T#U&Yli1P&%nSsw{HOFPaKY*_hN zZlBN<;x~qVF1=!8Tbf@5m9g={IHR~_pv)|Nc0~Pp>n@rF9!|wO{LF~{8CqJKb4HRp zII=x@tguRl9;%Mmk@r z2mUDI_PlvJJ&c6oOu*H}vVO%kx>=9zicRf&Jrncr_W0ZhCN1lN1mEy;ifOqLXsCoM z5v}6eyI}33uvx526hT3xUph&Ner8ssO0M0OK{n4g9xgB4(UtuZXPgMQt4vDW_f7XA z!GC(4RRs^DqaaeIM3|oAo+d2hmWGjHJ{O1Cm%#AvfZQK~qDD4$n@A7Br+l2pxZ1Pd zA#+eKq8AxMYeB5JzbC4ll<-)gpJZ#7n;0z-v(l3>NlUMl+mK6%sX?MuVxIZ0>7T(3 zUg$j5>%frGd_-C0VP(RiED zb|laD_YWWGaC&rf2lEkZ_RO>6V_V@i#ivh>zRoTjOz2$EU*-Ys8*{K*DB=|hBASDR z@X-haw~o=i%g#p?QF1a;^!u|P*4H`P?{N6wyG^y_o_)8k@*YHGdtM~uIb3U#{hBv` zhd%rE!+Tz*oW^hDz?M6a@`JY(!d&k;f>Qpq;|som1X4ED?eGWijit2}^;9o4ELqZ= z^S;rf+N4;@&QO@q--YpP+_jdv%T2aarjR5`v(BEcK5$HbVL0&Pyf&9L2ilr^i0fF0 zdswMt(q_Fl0Ls&dI-Kcf>#N4S)wl*e5DEownxow0WSpg7ABlO_)mMcX)9*nZ+HJLu zavkV@%FvBQ$IKKJ8SfZzJQ?xw3Fzn@h};W@iGPX3QQ7>m9QM_u!~G;-+N+ClW8t?q z`6k)Er}^rMF`D*LE&oMzdDH^0Q2Q@C7px7pK{f#O*bYh^af?<>%(aI)fKW5(VTUw zE(Y!PM<#*-=hiWgW4xHVr5%Zcu+0j_DJFW$vAZ$A7{*J%=gL<-YK6WKw){ZNjaHAY z^^fn^97q{s^f?=qdRxjxk z-6*=b`I~iC(#4?hrG%%K>ffsuukHg5;h+7KMqbfr^STs2u~F!|)wUUxcyCJYb#sOD zWD7NKkHqk{ey4l<{=Bt7h%=NS%~!QSMte56(Abx&+yb5d9mSyS#!)3hZGwZT>4y;Y z>04wcQKCBOEujU%;fIiqzXo6?B;nxT#Xl96Q?Mok;q#?B`lUp35H60|yI58=>&I)o znzbBmjaT30xOV$q=BU=d1izFSU~r^RB?1jw1?rEM6)Zy2`Sl zd^t8p8<5`N62V|aI~G{a{!8O2Fzpp)f6jemIFUovyF-1XCd<2$ZZ+@304S(MG zG~7otPmE^6Nip}`6+b)i_@r5x1dHLZ_jkuuj)(^S*;Lv+`?u&3EfJgj^_gcXV!?DZ zv;Ce)hpR@swT$E9aX{?{p3Y|$C4U4~APT<0*EJ{pNtqA)UL^hn=c^_QGXWwM!7<UL#7C{TTe_!?{DyXiuLVIaC0hA}?$`uml78=&J*IJ* z4rKC0CblS^DyS>zywXATl*k;<=~>H#g@>mU=%y$A(?w%N%Z9#OOXg0neyVmpauxwF z8=!ghN^$xK*>TKv)j+-vTTtQT!#%Q(k9bYaNzQg{GrB7!-A2ue_A+)bKZFSF_wZXK zBom<5H!K;4jVfgllTu(nP-PegGcdnrC~F`V)?Z=ERCj2Vdyq@>sQLhBk!#!kFjRVS zM{xn7h>iw-9o)4lE6mI+jDBZAJKf^69)h3}R!k3;li$F`eV;k$spR-nRupQN^I1uX zPA;sa#;DUd+7(!H}`RbO&bNkVTc5(YZzET58| zMd@-C!jTKAb1(Ps0&tP8X&}1K7U%Xvhr59b{(Ye~E1|93y2$mvWIU6#t+Mx8x^7V`MH~PAZm&3my@L6)} z<7>+A%+y%vy8E{U-#+gIi_x*FI1M3}rs>`WRo;5F#8o8}_#B)WaaDqNXQ+Znr%8Ce zTa;n`{p}=cPzFCo<0SIoYApFaF#U5xw$OS@AxfOI4m(C@du4ZMr2M{2`19@umA*-= z3}wU+7UA#36#n*y$rdVuk+9Yac}Z=19`pSkvw@@Ym41Q7)~Ow8tx` zexVm+mLaYCt&~4S1m+Tj*jvhZrMCE*`$0H#453!09WA6^;*p{@>S}R}L;0!1GEHdc zs;LKLBNz_TqH!q?Fqn?TVq;x>S{Spa|})@p~B_K zjnSiG9fwf9$GCQ~gnW-tdQ#9K{#F_{X>MXe)xJ9p4_^N|=9Gc=h%qoO;}l-ux1qZp zg>plZVvNhKzj^ZE){<8#QY@-B{2JY1|A1a80+MKySjJ&!*_RyDRX?`uJAMhyde8{X z4sa7~Odnu^^`|Y;z8YK=iuN>}{iDe$Jdp5gok?P@pp(IACNAFf^0PiiZZB+#(y23A z=TZ>%0{dP`hj3Wh!~)IGe1!E+VYB_xSDWkO zaM6wMrBp*ChQph#u@q2j={fV-lK;Mf>+q<~%Fm7j>R{h%S4QuvLA7)~7Q3(AZh^A_dv_8qf~{nrTnBXNp{ABl0RVpz5Q& z51!KzKfbn4_tqPw;!)!_1UkG(q|sl_GyJd8Gx zU^o2lBk=WTt{2Y4MhUUkXutVN8cwUVo9kEIlqzh}WOE-)6zVbH)=1ZM=C)bk)e)_9 zO;I#P-VY8KpZ61J+wP{Q9HICfpCPfl_#dJ*Q-xJ9`BWr@yJH4W+ zC#MJ!_}6je(z^Ra1#z|a?0x;dGRJUySNl1h{8!EBLS4C7$Dnz_&#eP7Z=k<8=Vp5N zM@>yfwH9;xchizWSir3YYzX1N01O2ZMVJox$K-_TfJkadq=>YTkf`qm5a^KQLiK8O z+1bnsP+zCRck=V(XWy6jM&Yuuz=v_NyWyO+t*)Ne4c|b~&SINy5r{bJ@FvvRXXh6j zna%-xM_nfT8PbE>-#X>K;w;n*-BIT8w!rTfnkR-H{~o_NVzcu{BSz%QS|2lt^#d4q z-fU!K|K*A1uB{bUHYUe3hMqtV(?YiRcva@okj2I1??&i!MJI-%7qN`Ge&vN_KHJJA z`(&g$Fn=*IVuP<(zX1v)T+ffCFG`OR0TJvKmI>P^ALuOHZM#jDO{s|16 zCi@o=4S)?b4cs|n|k^X5btM{Ej zeRtU_5roQT6ghTtce$8`WS2%dsl!o+Ed3Eb-XUS}Wii=oH3b0 z@hCoe{{b<@6CtB-JHrx7N+}FTKv9c3+yk~lf)}6FXpbzYxiC)@+3PyI=yjgF0o!j= zyEal0EUf;9{o}Wslmt0q7hAx_?Qe{^#X3g9$dHFK803?HvytFKJ1ClATHny|oN$jc zSu(%3EH>3()wkL|{hZTMN>LXm!?!Q!uavXJjWK8VzbnznO&Fw+ zJqzxmt!kL_XmGqZ|0?a>zVY|u%uqSuOmC@L!s{xjJ1wR2ldv84cN5HmW( zZdvWvtdCFhhUmTG=Ksj}#57{W>!lO+IEw}r%cR?DOY}fE{orSt%*9A6PtcYZ@lLPs zAz~D)>xW?@-l;&hFbmL~428p9Gb=KoD<|U@6{`4}G*=Ew%%EBFW7!BU%%Ng$MDizR zRk8~UW@q+nvkeW70ODhnt~JA-O4NM(C83OYCL*GfDbPMFO%EIYvsb&{nBgGV{#-T;R8 z4}YOl{OMt*X{FdCo@qk_A{6Yeh#Xp2Fm#zs+~V1?HDS8z^t|HhAQ9F8Zn)9`3r+>OkDCXtj2M%V zULyF*-=*8_1ohaN!Sp3G)i@>RdTZE2euI|)4~pi2g_6ZhzDF)>OWL+{x4xR~**&KE zE*ukX1m|yP*~x#WZqAag6Yu*I2M#8nj)42Xl;@AX8OG@-AU@8P&BCz$QK@OwTcp4I zQ9jQc3p?(=fAS~eyq5i%k9Z$Go_RIh5v3OiL+Na9!ssX7jH;a1WiLTWM5)*4W|rcT zT69%FaT`R@^+yC=CuBZAcCqpI!k(-XmBCe@nWRYswbqcP5iTq#Q!R+Bbe&m_l|lX! zZ1W!R&RtI;!a}aq4f?bD@q0dU_npajQc{1f)f0mTI7>%ZrR`58LKc;D*Q}%=hiT&} zb|X$#d^F4Q{)peF1ZzUXCx(fMtoO3Q}6|2oqI|QRu*v7uZw~CTAh7PQ< z=KWwUS57S?oL15K^^rabTcDd#C5T<6LJ_;t0tuM4;bqPqHQSF? zvnMbttm~f)QH#wQ!UfWAlaYmxNk^Dsi!SV56GH<}{^WVl~VoAbF7#@V+5>y@Na+ zRVGEdOTOQG}+f#7@P3ci0HfZ|I)7gg}=;J z4QQ0Bm_Sd9j%CbLimPAMRCULBlJ6fgLz!#Gt`TY&7u!N6?7jk9=UVaUar?ObuTmh{e81dGw*iKgI8-K9 z^=B_UrWWIB6ecbwPgBs#=jpweU@0kOmHL&j$i>iIC}rg&OTj_F3cLsNn>jdi-DtiBnU~X_Ex&R>UJ_mr~s2yYMhHR6!c!h&7H+em(F`^mW)d4ktbyN$Xx3i#+k6hV;74P4EcG z;QNAAs^#bbC+>clbP)SZi;+5WRPPQiw?-0SB_;ok8>Lqa6i;CmUdjj@%a!9&QX=pp zYJCS848oJ77^ZIUNN0QO(zOGV?nBO45pLo)dR#q2 zQ_|H|R7d&1#b7o~XkAh>gG#ePy-5frK6LAg|Ah@@PTfpI?q9nm&GIx~PAQ>5GmzR& zy#JDS{=l30XEOb~O#Zry#ky%+GU6h~l0SK^uqtU8?^}&Po^H`r#%Jd`33q`(kkPInsg&JNs!vYY0^cA|Z2F9tFajz+vy*S=cF#%L4r_QzD^ zm_aeh51)po*=EsvKe}JmBW~ycKJ_TLt5v4Nx~04yFdA;?}NzdFdZfDmK)FzxK5OtPH&x}1+wy}?i&x1I%@Hn z;AqU+O9uiUQ@cKL=lYBVz~b<+8-kLXgUcIqvjqPB zHrpg$IPrgJ|5(elVC6=qVwFO@-#-yWTC&tT-I8+NEcH0H-h_nmPV9gy*BURBYLFLo-f|`d_;{PWRpN;1m z-^%G(RyOr^$V3!PLZ7g`F8Etb30av=0j}(0$`E!B^uxH&o%u4YsQ9U>70Pw-9n|B@ zd|^-#-$p~SfYf2r?9DMSDoxu$lO0lsk&wY5X2JF+*aOV10WcCriQ6@Q53D=iIbtzH!-z(_MEn?$)Dp}4F@m}8{VPp$oZFJ^$1o3?( zrYTi7zK)K}`%rlyJ?#;^QJB=<)!40hwlmlBE6?U{PQpd)nRQrK>Xdycy4uH|o{Tsj zmb&w|Gl6F4MglL0OmA_G{a-QB6FmBfQCt180sw`Q0qCpLCYyY3IQQ#Mr7G8NNBLsM zZ}y*r`jTGe-pw`x{#vbyX_!Wkhwl?36rtdF>`b(fuMh0%4_b6(8J=*g_&O8jchUMb zMK-nyju+uIBN|EUyyQfZ!;5CGAZe>zi)2DIbQI*exW~w+8)!@rUl?*?Nj!cUexOI+ zJR|BnGauBM8Mg8pn+Sa(RZ7Nf1u@*UwvSjh z#7P9UVH@3otrGjjdGEu<45dhxF?}i&%X=1~B~znqOrXkvtI6j#hFP2htIieJ>%*s^9i%c$L_uZ(LWGF2-I+zY8z zW|C$u2RL@jK2`iGzl=AH3~0#jtKE@OXW8(ibVFIEMrrWAHXIwXuHuD$F2V$lW|p5` zc_?Ms>UhAS%0qC6_Di9PE3@B^lh|Qp>U)XbiGK5Ref+?r_Y|+w;2Xw|$Bs9{ zFMG!0X!CiJ%jqDe8?kX<+0+gyf_d#CM3<2H$X4FYjrl2G0WMx#G+cW??z(zJANL0u3P)-Q7Jd!C!;@}yxY zi$*_r4U>jW5~p&!40=lEYNaE^gUUd!mQUF64xO?q>eaR#-l~(9QDX9ncE1gA8{g1-3KDv}f9$V(=1!17(yelUt zl?E#H^RK30c;)_Zt|Ag{jeza_D0@P-CMJI17M#v{EG{+ia}GBN@rqB_Ey*Xl=MX$+2i^9MYqoC!4U zUthB#Ct&k?5n~Z6%!yeHzov@xq3=5J#|)6}6mGv9VLoD%e1i1fI_o;&k%hPE5*WD( z)#N9PD19F57f&j6PY5qV#@DtKJqN2c4@5$LGu(rk2w6ah33Ooo;m_=oZB#$L-3&BZ z7P|PYvX`?J+nPU*nj##8YhQ@7S)sPIYiZCwVr$VdZ)H1PmTlnq7DYZITn?LXD)f5l zjCn3{)jNF&nQ=mGDCD3R`MDErf>p9)h7cNDg=jMgv4FriUjzj{5$&#H?@~+>TG@HB zS92JYpEUDv%usLt8iD4<}X+C z-I(KB|AL_H=Icz8qK-ujv1Z^n=DAjBvkwX1gY&y#eWVCBS`Y4n4u%^2@%XqWyQL5v z`%o0IHCvwf`+$ zPtPfuscCH}`833DH#E&8VC2@hh*Tv|5x`J!iN;M7Z zlu);e@S0b?_8P$S1Y9}M`cg}2mMb6E^Pp>X%X7J1!{VAEVqge*D%OBN8EcNro|KK2 ze~pY7@ZzasuurFa_^F;@H?1E3yVyv{VDX7CF4LRZyu&&D%{B;iBuYceVet-Igi?QF z?Oh1fW1uPJ1D}VJurT)^i>e6G^{*jxgg>x9HLSg61;%Mcnk+vKc7H*VvcHP&NSeG9 zV}tDdJ~!r&RuvP5-5x{fCvLS7alD+y&#H^y-04hV8!wqrT; z<5xr2`GH?wz3=XE*;lDH5;XE^lj>dEwQ}J0G5O9S8K-3k!*y^;YY$pe0i^;Mb4}iE zBJ6)Rh*3iolQw1V$!#g|CO6YNRgJx`IAWyC@0)p)=p%p{)l)Npe;c8FP@Mh(oF~Hg zKSVIy3tw(26L@Xdz?qepVIQg}RKiljgr%Ciz9=P;$F=5tnl=p;4Z>s(jv%7iW}TnP zCtwJ;yoZ;hjCY|5BVEPs?827~e-u{ix47Qk9HM51lc=ib@=0?#$kT#b{ef6TZf9>~ zOLgr^qk#AA6CEm4&|3!KENUADtjgfzTw+9qQONRJ$JjJ)W1qGCB(mOKFH1%0V1Zr4 zZIh+TwR;6-1DNG2ADLK7|Cn;cwg4=+_>mKvnNI!Gn%=j-1=YJ+kZNy87Nw<`hjYL*mQr}xrmL0846cXPYhF8aUZ(alE*)=4P zsZgBoS)@>?5Y_NM_@>`%HFWo2=d_(%e__H7;L1ewe8X!Tp90slfiDlQlnXh!_(2Zx z{yHX8;EvAgy8GcW)o%R&zPVNtha93bt&itFzrT}ck2iNijeO(gx8NR&fBsy?GkF99 zPBAzBX@vt!epuYd3%)@e1=AhEy)7oYzWmX4Gg}=^Z==W|!K#XFC^PSKS#qqG?a}KV z`*=53c7?n(@wTZ)mK@m4WK#mMJC5lkn0ZgCmln+Q)V7;Qe48Ms6GU9j^`XDr3#W&H zP+@xk{_l5YczFM#754u@yDA@$|Nm%L_0-g~B>ZU^JLQi@$IkM;*J)MJC1e7D#z0%UdIH|a+TxN6x0x@NU68_ z%%|Wh`*!xC?hD@-e*#(~UeW$cO`c3YB)!F9Kw+rT{Z&S#UZK8E@lN?i1xTq*F-j>_ zg;fnyu|*OW#lIJKNx6VpzD4I@_|ct~rBk3&u2!j5vk|^NM@}K5lDR2YzM#6`U}KDt zP88ve7yCQ$cjfP(CNLdCb>>F2Yu-y4eEwmvQ-J25=7lH=uMbikSpkiTW|g+5iw1@? zJYDudPL|qr9cxA}Ew@J7Cfl?f>2BWcM$cXb1}$HM_uG$+kJt~@4+6E|nlnaDL;KOa z6n~02j5o-kKw+WAz5Ko2P#m~ISQ=OcZ1@_~YFzE&4(fi%?Xi)we5O_RPKVEn<4Uqh zz09}2#u;B;G4^tC@Du+2q8 zKWqwXpO@n9EbfNH+R?mBMM14!RKn=N1vF#(OyL8FyU%L8kRkf5ckGb;{)y8VqLYDp z2jM_SSe<)?chu|h!X09NV2LS}JfJV+B4C9pkXr#JP2CP)~8-*a2h!0L+ojsH0H^}xZ0 z>zvZI-@Du*US$|{@8=dV(8IsnZ%TF&(9pz~O&*}gAS_7EL(;LJ%7W^GJ7UZFl~2&m zP#dvK$TW1E=Z`!rV6!tobbrP~Js*1Qlbz%E{Cq58sq^{%hZbzCqQT=3UB$G-&KiBY_mTWpdUc+4i0))V|BNp*~#)tYd6ZRpQqx>*`b3Cc3V`5>Y@3^-zl=PgbIXH61>BeTK3!@^Ll@Aa2 zvb#)d&vJJ~iItU=jf1Tzhnm)XjApghSZ?fTii(7BY`|(jg?AMdo=i<2*hNHj1Ybzg zdpyA^`$B=q%?)=!58VdO1Ioy#ba7gUYd}M=6w2n@qpD#p7;^QMWDoe_ zcOLRdvx#TRKg6xw^d?Eo4qSKy!F|K2SZMl)cBmgr;#Tk&NM-NARn6c%6b-TrEQ-xm z-g?xVE!M{nPqGt<`EwizaYPJc5yFPViEswT6f#1(4M1&|O1{pv;eV0UEdAoBaiAs% zb8-!kI1AB*R9%#vSw@s$M3ImLeQ%%`^ZnpFjR9{56t?Z+)^&0My+6W2VSAM6ce=n! zOJGZqKq%#IO$Gta>0hG7&*2Ocixn+I6$nBO=!OHMDLjR$lNv)QECrW1ZjrxO3(#aA z79Z#1nW_`leuRoD3Af4+8?OEF@@V;Y#lyuaFsO^>b$~|s7%}-=q=bX8svG^N;m`aQ z3a7sf}cEMrcbx_8DTx*KUSCF{f+b zut;8u?D=(s6ttts49GpYxxMuf3Bi(_uQ|JRKwZ#{a3)@ozE5deOIvz%^(F7NJc?4Q z2gw6U>?py5rUN}3j&-FqcA-#op---^fe|O@%%uS+=l~{E*L1g`*2KPl>)gZM+LN`P zn-yQsR6JR`$rdttkO|Hh!cI(kNEyeJ!s6kM+R_rnA*2?AJ&O7Zu7~NQy7eoRh6GJR_+{z->xT(2G}ih_}YQz)_RXuN_75b*jkR8ijqCSy?~Yc(RoxphzAo1l+Z zbwg#`_~dxFb4q^dc_m1zkTm|JJa@tXZrnXTy67cdh?ug#QkO3{H}cUX-<3c5b5o#>$9D_<+pdxPhO+6e?i+qUF0^x>N2S* zL_Wo)P2g&QkO`YVw5~g`VuZii${rjsB4(Z$r??>a$q^$iiy#PmAR!@TB!+pQ1S(w4 zy>vt6r7f~@vue%F&-9Pca?gtOvh8qnP0fYp_s(n2?QievZ>>n|I~grsuH&Rw3JoN& z@dxwwkZLeDdGwfAnMrc*bVJyLi3YWn`cY`lN8VrzhN{dN?i_R48T1@eR0M7?($rY5 zAP{KT6~ZgQd%yM;SMx!)mQ*&2<)wu<) zXRFD0#;$0c40NYGy|1X`p2=Z5`=Cu!`Pi#_rc0Ifw+atnoDIWVibTVVq+EsNli_EU% zX9_oL5C-vLtz8r3Y1E%A%1YPP1`YDlib_k&AGEGV)IfXM=z-%lc(Z-ZXc2hzXwc8@ zpHPrA3rsy&QR#}9mZ^s9);Vguds!ogC>aLZ=*(KFhlNOPqmFT%U>9VmZGC=C(?$$c zND6&S5cn1+WaTUkq|6zcC^nlzu{9ZOjix1_0CDQ_1oC~Q4dWER5`>;8WCvUk{?435Q%Wh9H z!4&+tnSqecI`A&Rpx&_lHici!Mhp9<_oXJqkba$m>DUi6c! z^H~Fozf<{_&t%nKl9VZa!Gx;7Jidn;I&Z1ier7Gs(E3DsR$ntmW3;))%?Qk_)?+tU z#?qS@iEAs4PIL&C=vyzPpIpJ7E&p|4sTGdtvU5I~(quwdISM~|DB6~Wa7xRUkR=Jn zx36zB39`i&BFd44Jo9!v`VpZg3i^y_Lj%zvL)90j_)QA|2RMw>%FSFc`!NiYSncOh zZ&jLn!m*Y72QNUliD7|$h-#;=PlY-dJo!g|DkB00`_0Fi-r7uQEx1cv@9t3&F-4IsNRFfL$GlO9L+>VjcX0G8&mA$ zr1Xtu=r7rWrM9k=ZL-=H)d`t3`uH_3kKBLah76)Vj#>ySlMG`<}-*>8Xa|s_eb#XCT$JL*LaC=0XuEFR-Nic zWcfiSov88)sev}N^&&W2V2>H3=n`RJCxvm`f>vC_W1VB)ABn!$w(Y)q84b>SQMnye z>GWDy+7u0~k5*1p0tA6UN-QUslpx)rC!0!_KQrSy0ARo>)5wf)gm+4P2k}~8l^S)K zgD?zR?zU>6*RFTkGgxiXh0B#2DN3&{T>igo`|2O5%Aez+)ddaCT1Ldor*b5r0pU8;^bdQ z+g)BCXj>M=p&Vui=O_x^* zW{wqG1`1qn{6V5Oeq-<=bYzpCKk-w!+S6~_AaUw@OK5DSQ96AD;4|gAjw=f=OvhhJ zGQj3&bb(6SIef)?`=GHPdazZ`hxh(ty1R#C@9Xd7EGcE|QpNy- zmM1g_E2&yE$2%Et)4H1H2a)A~S?L+qfivKz0!#1cA97tPLW229bL!4b^Epydv8Eb@ zKbap$4Je=Nz64Z#!B{Cw``SY%cN%57Aovtwx`XWdt|hT9$$;etxl*Isvi{EB@m$dG z5ec@vL7fYW8{Zucy1K|(vy_Kcai#aoCnW)j+wZKtcyT)TaaLH2|IPS8w*e{&uU2`70?K^S8rsVrn`yW^Y ze!)s$%NL!tMu+}7RM5HZUKUg z*&?3Qb$zb!R2PQm9?jB}|(jt2P@d5I*6^yxf2N|+z zvgz)FT}vfvN5o}xXvxAOmxb)YA`tK5OcPPCLLLwWUC4j(f}l~;;L#W!U^tVRjO>Y3 z+YNM+8{&y{wIp^Awg!jW`a$;qoHCr2x+cND!uiHrHc2H%5sy<`KFn0#i+UfA=RKc2 z?YF+KnZihQHdwx?oi%*s&3`!2M}~z2VywY-H_c`iupi(&!DVD)cS75{1}+Ldq#L@2 z*$;Y6(}1(6_GNvsWfX^)o8W@eiz>fnIJ6K}Hl3SuVYJ<7Y-X1(2J8J8Ds>27LxlgnqchVOEnT*xc=U3xsK3A3%h zjG?LI8nTx~Ecu;A_jfnie;3}u3;OHAMQkz9l}y`5+8G2zmrHGy!x3zc7}y^h+1&;!Q#mjdHz;Y?$kX5~jdxsTj&WzJEl74cp>Q&V zaK!!BD+KP>`gzkW04wxEO8)ZB5!^<3JY*o<=7U`mDA4U_>-nU8GQ$jBBW@#FHow6r z`EkPf#QDADx(#eS5*Lsofu(nJfeEFpC1)A)gj@NEY3o zAioM$3o}NtEmlakBNqEugtQB=L#y)Fd8^Mk-KUXjxjU1$6WF3IG}sQ9RYX6R*H$@2 zH)>&{NzAVlhIeA9CQR@z-WQmi`(ez31fd|H8)zu_TSx- z!otOaSp7b&h+W>m%o3tn9k0Vvd2FO&-Uzyt9Z_~zSoS(+i@5s8zdvdM-WFALJ$X>I zbe8{!jSTh&`o!$1kj`(Gqb zQT^-vzBNIAABuvRB|%%LqlrmsBtZg*ICU}Xzv6I5G;u!(DeEPu3eXfQ2;uZAE7!3n zbnKwa;=!#I(Qeu1)4XRP#pF!?l#VXW(_1ALSuo#!!39JiN5rgvFg3O94H!rhtx76O zppwL6eqn<%_PFaeNgRt&6)vUIOm+*Z_CNkYR9QnUIehWrFa)KvgG*5kwTFp&xvN$@ z2!oU_W<;8Yfa4#&jjks*oN+awi_>44ANCW7RBUq#IZ#T$glda@3=nsVPm-2~NrX2} zT`})^0 zn)J#EQ=Gjx8$J6P!o-=zV_pF=jUpYy*dZL%bqzDB7lS}J+seOP-%orDD2|@u`K`<` zT+Sp-g*lyIFxT8wv&iK!ih!#s4?GxN83Wu1koK{4vVO~0;YHV*Z|IR-gLe4sL@3y_ zD0W8k3JFO^(=Tcz`xoqwoC--*fZNpP&2yVR-|=}3fVLFhfpP!(NP!Y_6o{EK z72sFF7kT3~eP0`+hQ<@r~)mNy;^xht$tvFsJ z>!eJ1n-YIWmu`AdVxEciCKT9QqWz;d4!&jddF-MOBoSA~mdssN&LJSi0CqR-?+%*# zXEaA5ULK5^77%39{d>SkRVeYyq;^m9h71_*Tk-`^Qe`W-rIGX%DyFchIgckt@0Q1L zUVECL8tNOjexf2y3|&LtKfK^>ys ziP%jQb)%J<2%jG&ex>mk*wyw-3P69NOHb3%qeF#N0V2fDlcf9o2&GC4#Y`+%T}cz6 zC>ciqoGu^K!$A?=nlU@&C!NxGFVqt&{8hXn)7v=S_C(b>OXGQIC+_7r2eIG{&Gmj4 zPgw8JaldFCb#Of)I&&s2*k?(nrh>V z=P3=c)EnHFCi=gtgmZ3&(U2^enVynwXwZNFE7LIE4AFPOK?MbM(aBhuCS+-KcPP79 zw>d4%ISYOZc#;H^uY*4e{T+?5J-(jq>8(h0CyH)*)5dT!CS1N&rmSD+QKbsfkznRJ zAC{hAw5J)`!`f);2lX6{tYHOgdHo9tQ&OIwdPH)MJN|>VEk#+>G_Osn%y$%brjOPc zotrmt96dCcN+5q@;K(S(z77sQv_1JId}|I%~92Gc-5FEUOEZ^y|h3r7?g=2*HU&bD&7cK_&g;IY|3sz%vZ1FUx&DErgE&!T)+MeF*%Rfw>-OCyRYBA zy$0dkAdLf@`a0C^F7a3Qn7sY|P)b{s%;VgR|AF-)9J;WsVwIrxldmO=4U^J3oHPx~`ZI9cY@CqN2 zP2=llal@X*TP<>P8Q+CWW0UZYZyfqNyq-fmeeF!ZO+3Z$XS3<__|fg&2;*4bW+dlw z#X^Za)f?S|TDe16`U||842=&)SD?F`)EyNSRplS6N|Xdg4MiQQZje+F+$Mdw5zovJ zUZ%2V^Mu2}z{Mo7Zc*Up^!#0$UsB*jbz2IX`u*5A1 z08l}69mLpH;7CNAI=n>i9~{&ojXu2azN))hcNA|Zr#gNXY;ap8e^a5;MaZFBK;fx= zP!TWde>H$_$=1XAmI|aL(#?CZ^)q;$>cL)nb#V--J0jmgC*%20T6S{P{xmGiIC263 zUD;j4^|uI8oS*%U=(ZP9TLhXjdum2m|GA=>7-za3%JZX=y5l89qb0 zBIH=pQ|OF*SnIhJHePu-SOSb!rh^~;b4HhDzprEgNh$K9 zg%V*adFLI(!Jg!?SP}8yEnKdfR&orwXdnSN0LdP%@~5ET7MIK1^Q(`yM(Wf8dbCSt zCID*2_$gD%P~SPBXG1~CjuRA6H>IVS1T9ru0q>yK-K0rTywFCL!4)+6N#5b(LxK78 zW_-_OX}NUs$U-u>at>%{ms%86gBIA4MZ4yBA!XX$bBPgm(TG8Xz(M=3OBiw(pw_y$ zb$Fdbb3qExh{?W%a6_^%ZNSIp|MsQvl-VccU4Z7iMQ#_kZDjw7x3v}!fH1O0zS63H z+xMKmQ@&zPA&ape0O>U>FKRA-9*?2gS89XV1Tgqgq*SOjVP>#fbtXNj zxIvom4lCBwntOUY5D=E+w(PKdPs0m~2vSCM`%{xIw%(2qSkyt)G)Xy)M+Y8Eu_~(Z z*kGCC5MC=G)K(q6&Ht%6+VXKXwY4p&@|y+IEFDZmJ#<kel{Z+KXAb z8fg6VPqC0_mn^96_#|dwySynjV*(2w{4BR!ZzdiT6ry1Cd^q~<^MiE%QA09gNhL4{ z+=04hW#ikwdrOxf@K~|y*{3|PQSxsI&Q(@P~R5GL39qU09`I7vu*33ixI!Dd}Kg0${Tq98n{L+ zBUWie-aLBxdC%x3XB~qRml;oQi$eN{i-!3ovfcfo?*n0>f`uv_Q&JKtzm*w3K?4P( zSj^xWufz0Oz%*}v@9!ww>eW+|(i5M~UYduEo$}m}!z%%H$j|=wnjf8*))%Cvmi*F1 zI!UOIDf9fj{W9&-OL&d2o1-q}4fiJnjRIf{o?p5YNpYt7!-TvwsH2}EZDa6(^W3bB zym613!YTCLI1Ln3bnS$!?oj(u)Dj1{s0Y`LWzG%MQop$TE7d44WQLEK)m0q*gL2%o z&NEBl<_pU)WF2D1#(ZBEvG}R5g>#2(RVkUB|CKR!f*qM@CV59E8G>*}n$y5IMi*7} z#_tp469~&Ix`C*?YENA;S<&THuH7aM>S0Nq3fAKVSJKb}C>I z>?WpBT*qsrULIO$p_5#YD-r?5_5~cb#bj_{p<&4RcWeuH!*>Wo?VL~xMi0seA`!%5 z=+}FG_V%*uraSA;`Qlc|*r2gYasfpf1H+z|<(zM?ZN&V*oVN+O#tpKoTl@A-xpxry zzv3ww3WK|!(`{ZJ+Ays}xS>3C+KlXc*bIjs-;=B_tQUwnNCV_*o=;nA)#qCM!vpb+ z|IlzAeWHMdg!aelf9{*p8}r(yUE<(9{TS1!Jap!~8}@JiN*xB6+B}^w!7O*cJu+0$ zfCb?@_8y4i4@DL;Ttr9-ac@2L#Vc|~h#QnvWmC6nS*i8nVz=p%tsXwFWAy2oHz-@e zFB?4_EyCODM#u?|g{&?jkJfsP%H>7PAl=Hs=n?UDNk{WP^c_ojz5#6Jh~L1o7$6S6 z&AQ$r9XG%3zW7?Mdvj6jMA6*$f!m))E_XtBA1a$HxzsL9`sdB3nj)tlkG}?8nuUKm z8t(GCUzz2_E*}ir-A;5X4J$<)EPY}S6ciymD8(Qj07wCX10+bogu#NsV^M;UP!G_g zLcoxbgrcHY<*F5g|N4r>w9U(|SLVxX&5fpETx~1b8@)9e-(Ig=uUXx_-LtPgi@eNO zyGWGiVef!l==}Mu>9baxxm&;Z)}MbrsV=J}Ej9}c4&%A}f--#A^aM65i;S-F8Y2Gw zPwc`7sfS(IZ7S(z&F;(UY&20V~L?Z&kot@6DRgU$A(T1HN8^v{Nts?Z=5BND* zAarYj=#?RdVI(5#Oj8(cUm7w?9KC5ACYiCcSe+yqK$Fqa44Qwu&27UDV`@i1Y>WCTI zGu-zh*o}>8Ela9pv{lupNnBc}*-zaiJloA%%TqTP#;jXi!uEa_SuZ3;WDCK9+)ry6 zOkgxa31OzpKk#r-baiEomh4F$Hw@!}Nr5-YEh{g|hFb8woH7G&#*3N!B3-XIsXLA! zSU&vc7iCuV&aC5TE_(`wtdEX?yqBm&#ZV#TQi;A{+Z(qB@?Q0ktg8AWD9_w1+lmYr zW=E-}sRWhmQW_fQB^9kSq33r0LdtF?+=fTe)g{p`TSE&DH>vZ#wK-#ppE30*y-OX8 z;mNqOY0zf_1D+BRnT6%Cazn$z8WtI-wKQIR%Wf}OK^eowo*)?kB(-SfKQy!;VH(;! zeP*TMB$2=9PNMs+vU)BY33oeF>Of2gqS(eOjB0PHXgN)WvR2N&SlP@8~6 zZ|}4UPK@c}61bwaMj<;>{KLKNT5S_kGx|bapamXbR=VtS)J4a6WNNflX7+j(X{} zUO}wyZ|NFiz{;BeqNpsFY?62^o+s&040NX@O~}wthdFJm`j$! z=Z4K`RvJqU)mpAFSC7^FRyyWohzfaa7%IFBMXmy2K>Mp7E`9>(3zPN=L6U>}oYEDm zot_A1410de7>d;Vt@e)_vAV#J{f8ekWVD}0m3dZZcO7yU5y(!2U&E)9D|%OXZoi1~ z(7X|NcRU*;%#$>B2%#$&b3x%9z1poRo_tVG5Sz2}1-H3-$ZsHk^ly?1YON3q+ieLN zCb-5N;-1+8HLi8qL2w@TOe30f>|vz|HJ)@~ezG|`AdV@`!F}?X#Wc!{GLb@NEj)G9 ziDLu&Qd}R4arbYbAyzHvTlivmWuZt5xGu~uHZMIdt{)cuS8wu< zvu|BxbuP$W)cLNz!1&=Pxx~DAJ^V?paXx-;5j_||Q#3zi{9{}l9dW)7LpMJq74Nd* zhP#wczQ&;Cw0dqwXMS4F+)$N5qq)x*e80rfeobB2;dkjQ98-G?UPRp4PAR%N*T@Ve z*b$rr4=twt6H~gcnsP^CqF4!DOk!*c6JZGCLs$RX9+6L}rxEle+S(pmq^EaWeSt$D zFyWG_xg07$7W3i)mf}3r)CM#vGQvhl)t&4RZS4TA`1y@Ob>WXdX`k2@UO#xmfA}L* zV$A^*$K&o~{9?g7N|m*Rv&*Pt^^_TFBZG+%UL=^*qy^A2#7kM-Z>3)F>#k={WzD9;B%3;n98=8V6VEPK&!w zr)Doh>T4|B66abKu}6fU@-sFpVF6JtlxdZL0lh=!>7mn&sOgB3{?AsJp*Aa z5~LiQHaH|p$W8>iI5+zq5@`=4Uu+77R4BUaq1Gt_W826z4@xv&eaRO%TB!;d; zA*k9G9a$4>lT!q`QudVVh>2xZji%@lv_{LwY7gg{B0={qrW+u4*&go!mp82-FG~#& zASZ^64?E@G`%4(%e$6JX=#2gd#Do|1V{2EqMVYZq>PAC|5ckYPf&!8uTMtD-j=%P) z{#MHNh~9$H{NM;h#tCp?w{vEsnowYEs;j)9QT&r!&I#>!w!2*k!a-h=x~Tc1;eTOF}PTlfjMd#uwnw%<=z%nto_3 zgXh*Vn_WM4IWj*W)<#16f4orlZsiF5Oks52eY#C1j@F~ONr%)Xer+_nqm~HNTu*P1 z9|8K5)ds8I36veCny(YryUQKEG`}nFbj#TQz|JB}6`J4JkL*VcJ@$i-ChX?z+wP-! zVUHK4uD56Sck3R~{O*EvU!9A=H5fXB9#Vc&NV38~=ZlssYkv1sqfX6(*QU1X>4in< zaW77tS*^xSo5n}ySMhD%!%t_?w+>0?TG^M<`;6{N&TZ%V#z#SAfn{NTyY<1+O~k@x z=cMED?XNBRHs}4_!}G%KJNXwo&HJ^ndIB19qYYBsSO%Zk6UU!>x7qE8y%|5Lt7)=>oKnzV! zc-2swv7NELzD_}y*Cs?9M+mG4w8&c8GLO$@xePF}wE6qQT0NT8)NaLK(HTWy^V`+y z{y|F z$&os4q7<4^jJ;Sv0h+8>K`|0nIzfgiRXLJZI^ho$G^Gi9@zX0MRdJ-!iNb`obbFT4 ziQq_Bh6Z5*0iHLN9exvWo<%go+sKv?h;C*7t(7f&6(EO#)N`S;Ea&uNYoB z4)ZEMh8RI?!Vn|VZ@3TN%i)^eFxn7a^yA1kIX|ths<+SA=L4ii_g7=^GZe{VxW`jh zFU5_twd9qQcOomrxr7u!pfjVWF_O=C{kWT+Whg_xKoX9mowV3QP#WH&@`>8aud~ph zu;c!*m{=6Q*4N_F+ES@ZI+L=*tr+g8)@H{hLAmkh32uwpY(X zs<)@`h4Nbo>8ssDryP2HfH^Z(v!|ox8@-+(Gb1aUY*#xRKSMG%Z&jw*1|2X~$c4}8 zT$EKL)E~hIJ=df!( zkYaAFuX~58;Zd}>{ZV>NYQU$g<*7lQjnTFJQx_vQrz8ThEyAYDL%M6O88N(;g5-4kD4+Ke3wpL`PP%d&(Wq`5jbC#L~IU zRG&V}I$u`zBs5QNqCNZ0cn~|tE^sNH65AwehNK>N%QzR!ExNxX3^?8(ZfU-6FQ`C* zqpepQpTcr4<2_=k^b~nxEI2lgm6N6oK8-W1^c+F4Y4?5^kph}d)*PK6xL%^$gLhgC zZ`c4?mU;7IpZq2;ceAH?nVEA5AVZVkY!zj3d?6@o-L+x%JqLu-^oF^@qD+^t9+S=! z#k^jN_s1>nedK0B%dOQhrKu{~)_FM)9pf_CsBqxy4U7#^aAgLMP!~%6;$470azyJ%}eESFLL%awNP@_zGn^*l4a&!&Y z(+AbbR%pvdOicrvwOpD!<%^sIf#RnXT$)QBxIO}K>X=+d;2n572!(8vo*wK~$=3x} zF#{47J-!yN_YF8E9=*mqIOlBlSnWTuR4NT{U;%||vIQz%qR4E4uDr>Ym2%UYQw^(_ z+1HSBEsgM;Y*e!Ha`Q=|rI~zEF9+d1rvWi;4(#p_F)}0CtBN4f6#SfCd4Wrr&#;W) z(cNJn?Z_BM`-K+(^Mr@%t#McTasLH-|osUi;rK#;%8Xn^Oy+7s7rk;e1V8X!zzTN?#P)?JjX; zgT&+I@k^HJROuw^Ak*J+p8!G5{h?q+CN`-*NO->@ZZ5i~*N7o`6}<%^l-M*B97(14 z%-19ZS1p}-KIl#7>TtAFB{D4-FvFrrD+1@=l!i^PO=q!Z6NEM8Qp5Amf;t)j$(EQd zFw4X#+9c?l3R~MdQEGj+6YCA#-~gC7dHAl5YFh>{`-h|nFKqQ(roq-9FulGFtR5-> zy-u@GJAi*JP2X$E>B`!%6+*AAFRz0tJG0Bl9n~ItL&~wl`h#U#=~`QPO&PJvVaJy^ z>cwW_S;iT240J>8x+iNl!&{Wh*}=hoenyvm@86XZ=HFCv{IlZu4-MRf^}!0#+24n0 z5HrtDp51)i4KM_}KVMq@rgWasi+7jqFyL=&;YL4q(BOn3ngb83k~~(eAUJf`no}R9 z;U@brfRe@D`32h?91N-aOdh9;gpVB*e`oV&jNPp_Ww4x}BqjSVZd{O8jEblxhJ~}+ zv%PkBh<6xPnS;0%)&H{A%NH}Jxly7$PbS@|Inq&Sl)`N~A#U^YGS4U|KNQV0`Kbz0fq}t?QYLHaXuSkFC-K*Cy!bl%=&$I3CznAJGL?t}IW1{c zqN`)XGh0d)&!ZQ6oO@h1K)w^Eo+M7ccusj(b{~6gANgkwTMIf7k&hhty!4sC>g&KI z)xG3A>AItGF1oo{WcazfkA1qJCGKCNd7^@ko$UUT(q3Nmhv=0vFhJJT%VRsgvMnr~ zm*=pDkL#rx*+08YFYtdkB=B*I)6{YC2l$X~*axU&EY;l5m)W%x%nE)W>K?wCST0aU zcfdFnmFM_X%m6UPpbdj@PSJzn#>R(2I6ZT(d{-4FqwXj@zs6%saZElrTNgwiX4t|- zNn=CZfhEwaM}WV$BSQW(-VA)rid%7}Hh$8!q~ zJC?Oen^Raw5T{I_r|_ND{%s^)uQn6wdpp44PM?cUqhuzJ$_|P?PMb-UXE}W~PM`#! zdAz@`RmL=36)V!tOq`i*kuWV`9pR{4Dtz!(^b4`JL5uZAcpjf%Dt2im%8jMpoCbpG zkbdO64L@+Xe`Mj-6Bl2k4^k*BT$mCHcLR9Xl_=QUYG=Xmxx&u=^A+mT{P{vdY{nsk zVi>jZpaoG^F&y~R=i1FJtV68|e$xMmHGB~La}P=D`=4T(O|%q+YtHzX=sA|g2X=+H zDb%ZbCjFr0#_}#mQRdV5b%RrMTVkmLK~|<$QdwiVc52A#uq>Ay?9Q-X?r5QI-{P7r z%=?r%s61rHzMKv(-D0xLxJZy$81a4yy@2J-gFJgYyYCEIRqCowwu)MHbu5*#G;~xs zaZ6O;=XO8fL09Q9%+)wiQWp85a(wJ-{k;6Ocd>gZ$(%7*yE*8<6mt+fWAwl>O!)y7xf7-pP6XaZvabrN#64-UH3u|s(4-DN;7d$>DZ7t8(x!IBD9_FJ)P%Qj6 zPF^*gBD*bi_)E@I48tzyEG4fpGZ7azNs6Xi2>a%a8@(*F_D{}6k8cZpB*#`Dmo!O- z`9@|3qOQ*>DVMQIy}Ec_q$yy1h#Q2gCvA(;8O38s%7NHH(vEOPwWl^K=JU^N3w6>W zt){e0_TRkJNWu;YIzs}uB=ur+QmyFU@^B;K(D4{(xH?|@5}wU|Szo1T?b>-w7l_Q@ z!plu!mNc95M#|Ww#Tu{0NDGs&*}~2Cy4%fyhc6AklY6gwVW(VHHc_2<;gMJBg5VT> zWM~VejGjyB$a6AuezydJRftl;m&zLD3sFM4EhFbIof{(JYUJQ#qjhMWlJ7oWsvU&* z)3DRYzk4Vc%;FnnwKhe>_>V0-BKfpPIjCpn(1gfQiOneRqaospsQN;weyc-n&7`pa zZaFLM>S=>^Kj1bdyOIqA8lcV_WSSQ4OE5#pEHz$Ru3iB`Ki)@i}eHHY=>T>o47I}{5&2_V6 z#l(PKH(ZHPN%`{1uOF-LT#vv1)eG7n;C4#%6Z0EYg}NCmzvLKc-4|4IwwUX-0R(aCxv(e>j;Y8B zImkZ=;n-!xp=0xG>O%Tz57cvZ9WHP2kDKAm5&K#?(TGMwM5b2V-%M|CNiErU`%f6I z&l`e+(4BE|APLWL$|QQlb#Sj8=n`gbedMMuG5ypCYP+~6@!dp7&a@K%8edGR@sCs8*Iwv zE7&g2rA0K^Rf%Gz!p|o9qjD!|!~O7J9QQ!+5wz?yAo+P^P@#AF=t5}dg-tZgJ}<9q z5Tn0xBTKGF2SAaP?_8_nguJCd#jAz-Ap}w#?u9CsBl$yh>S6=b3|u%wYwxvP;NX(J zBPA8Z%G+S+SebnJeh?{$*Ip1J5s*wd2p*#W#fi&lRta|;d!KZQmah2TqCyKkXWtiz zrg{25dL8z%xspG|6apSmFXv|3V_UBT1C?xLqIs==mLK;|9ZxUPvhhe z6TOa4T5eS^mk$x-v6&zKY}mxv=HlGifNep(L8%x5)EfKc+OVyvyIp5GH%GZXIOv}gkfS~k{hg< zcgY@?_E&puy+C_hv&+m3+ZOjD&Lf0>#ss(zM17>XgO74vuOI0~3ivi5ZVx#|a^>Iw z!?%2dG07tV0+Ea&BG-4cKca8S=I%?ObJZvjvyDPxra+qU`29jKhYcp)hOH+BX<67o zm$L^bxy_|N0+SSRLxp?YZzq@Ui}vp@fu*5(w)GllKldPP5+jxlA^bOzt_71s( zbx;G_8vOWyY&{UV@FF`9BMJ6$%RBmDMMJY0{JCwf!Aa*gNr}3CO0XuRQLGFG%PJBX z*96kFTv_s0b6al#-%w^KQhhAL0w*#6~BgN`#17i?l3)0XDyfzLR}>$h((do?8i;&6;?!&F;Z(i&`? z-~rn1-b2YC0lq-SOF_U;vkU;bsb-pj0NzJQ9>PX8NHMJ(kKm!6l153_0t%r`N=z^- zh)1UyYabE>(>Y?&iZ-R$`*3}SH*g|EAWMLP=GBnCaV3L zN-kr+?oOvW<6_Yy*-^VMi7A-3kwyrCS<B-g|ye+TBkut_IW!$4E{CsG?Zml0PepUrIJ3b2QiLp)_ zAx*JrZh-a=Jz1$ob<8dS#>ixK@&5$z#;D9Qk)PY^`3!7h&+-R|%gpnfRTquDeEtt* z=L{|glq})7wr$(CZQHhO+qP}nwr$(?+&9^7u*nNfe!kASy6P{G;(w7t3d31tZY$i_=7{4$|I-I4o6%DUcb?$e_s`Du`2RHQ@rwEmaA+MPHx(nK z2SRRL`lhMVW**p4)i5wpya{jA6`6Y!e2lQ-1==Hk7NGc&zW7qcFe1$Seh>#&c zhcPLpY1yD5o@|*kgqaY#Yg*RiSR#?O%+gw5Rs`BcEjgJ3R<7@`Z@P1mR?gX52#V9= z@q0TM@oC6f#Zk3DG3`O+=Etfhl^BaCdN1oT5*l=snf(j=Q^ys9+A<0(>)B9kI4mn{ zjSa%z_w(!hF$8UdB(*U3_o!@OruKpEZhtOtRFEz7Rs)SWhjr3ueJoI8U4R$T8?V6v ze6)5^C)d}$^uhTE9Dsv)GePunZ-}r3LE}pR@J?Nn+JSOplaz1VUBw_>mw10IuM^rK+`XFaIQtO`vb0DX0kMxZ6A7&Ry%Wv-ABHP(ar~ zRnFNQOEi`b@gYbJVSixIgZLg4X!W7V`Kf)Kq7RInP1!-&>&L+5=3#6KthVlKysYf zDNXz5JOvvaY&+w*PSotqt@odSH2cWEAFbCD27|EmZS|(QoR-l=?X9`>eGmddt55hV zqGdh2g}D;{{P-D(T^gWo@5E%N5)&4pUiajP;CNAJT&Cr7CD;cd69c?omkv&J;#KdsdhysHBFCoC*F#y})lLuQrud|8{-@t{6ZwioC6bxOwG~8XB6(H zk1J#3kRzQ8HM5s8k}SVs`~jp>q&fFvdCYkHsqV<(?5fH)pVg`7eSjlj-4DT6f-z`ViqUEOs#1Cu{&O zD>~xVhYuB%EF*v)lXAzEIbsO@PIQ?Pf2|wS$yT;2oSEaQxk)t1fnoxAG&V0FEE&<( zRj@Z*pVY(qK*GxBjl>VXvgHOSzWR*>_|Z#U3=ieJFCt?Xr58X#fJ3V%c>l_o z^M&9R(N(OJc<0z~iF@kF2jb}7LQ@tK*HsHN)_B}($D*_DPh2B^;sBQi@s{I|M&ZVc z-cD#trfp44O}v~vhY|nshFtMKk=IGbmd1-9x4To(Fef6r?qaUbuIs3_u`tBoPT=zg zqs9!JS19chZ($;Gef+q4FW?`kfMeeRJ}T%f;Dwj8cz4*8@xL;J@sWRR;s&BXF1$L@+Hh_xWx+y|U|7xt_GvR~}zIKM0+#ZTibysw%z>&>HX|F-Q3`W%yex ziMB`Bh%dJS$MAHgICRtuJ6obDxnIjpLzG-kW1KBeD@(Il0N8xxRbu6givx=mF~FMy z%@nVBnWEtuc}vQ}I;P1ph3pom9mE>El*F31nFEU&D!>~7P2_V#;B%A%b1+NXse*N1 z`X_#dwl!JMA+<)b()v;T<8uUcRG$bS0WJpndx3b7d&ly|QD6GY-QXcC51*U`eRpf8 zk7eSix_B}saW@HS5`ro3fuUdpHmt*=8)^XpE8Bg>f-49&Rg(&UgfY+IOY;D5*?=KV zLu%X7j?YX4a8z$(zW=p(^y!+qCQvHH@rfadrU#*%(k$ z37EXuI$&K*{G-FLtT4Eoq6P&^JA3GaSHSm+$85;z>#Po2u_pp6WR4&y21*$MowLAW z!nRW=Zo~VRa#P^dI;1^-bewkfxL?H`E$RY6H&Fe@{M@*U2~bJS>rMTY$)M5RaRW=h z)s{A4f(T_TZF|ex19=M%J2+tgJlwlz$Znq0`JJgp>njzOCK!r4rPeVB6DscL0V?B@ z;<8*Rxl%n_c550=S6UYAJE>jrCYSR`o7QMGeCPFLp!cuu{G4S(7%Z=rd%}V-O5zcr z%3TTZr|37V3N(pWILv!9Jx4<6E>nD-l6;zP$CUbAnt(ry)T01joNq0hB9Hm@O`04r z9S0LFWo>4EkiS!& zEud@;ItTLVQzo2{#n$~@H#$P3Cgd|g7?~IIii`K)!~3P&()RUI1N&&}57m{%uAtF&z(#?i5bqM8PZ=xes`C- zUbAIRvu{35iledD8-vK#KM%H+7c-Fyd~Vz?pY#H1!ZKTtf5xmHpDq9kiqbA%ckRkX z-QH}ihcO#(7HYVbg_w_~3H@b#PzI$Q(hk5qHsQBYWN3ajzMnc_IsoUPpEr?bBh+*8m@@qJzdsL zu{1?_0H1!vGo4^+YrHQxdo3aV1?@c)c|9(X{Wu4n7Df@3a;J~SHN}WXq*&6glaAQn z;fML=<-V->OkOkC?2~7PjCNHqN#+655NzFIq(d~)Af$8UDjXp_V>kR)5n%=D!P5^t z?3&K#jK&7$``g(OV51B=RgTrIZ?hq`-W9q3z{Nx4=Cs0}b-T!1nb{~NwZ(W~=e_aW zXv)%aT<@n$Xawtwr70_!f7Y19`#0@dv*Y--L3sn_!Q<#{f{KVZE~vEzbi)1PI_yPA z1y3RTgW|&UqOzSQ6KN|MwrwQZp`lKKG^5ltTIO*NGu^Ggdn>s$6QIg+ZLTUU2!K>0LNS|kmzJaVMY%MlF62ht=1-?e&PKZ337!WnjeonN z95{V?D__U69fR)Vma|YOtRGJ)K}{2?T3}gvT1zLRd03p)k=e~rxpcL|h3tE7O4goG}ukf7X% zM6^Eo$HE=Q=Hm8-!ICr!UiVD;QeuOD0R6EI^ZE@{7d+f{4QMoc|y=PWtQxW-Nf z>*^}~mJ#~O>VnNSgomj!wAJ3@n%7*zmHn!3srsH@_R~-tOglcC`e^1LK&6ruc2xqc zl2C(?=hT$Gcdc%-5V)rRYyzw$!p0RyAoo*}LC2!EquF9s!4`Eh6Zp$S|EhNtXTo4l zdP!){cYfqY_K^=1_4WztHV;F1n_j~qP=Z?Tbk?K=As$%=!}2#UfY`GUrpIo>#2$@| zTrUru;TQSjjZ95}{NQy{Z^teD@vz|~P@x?N^q_pq$@tvfW^<$U6euTo@AA}Nbja$j zkj4p7j7YMq-@Gxfco-o>hge@J*~|dQ^R~y_EZmf^FCyq-*QG z4CR8kkL0)bx6|O6Qa6C4gJ-n9BTlYzSgKKLeoAnXn|es`mN~1B_l2AO^DqmXD{__M zviX9{JB7zZEjCWg#JCWjz?6LE5X59N@hCoW=y2YsD8JD4V2Ypo8k-!omWF!&=AZ8T zL8x_OWSRDk1;TZo9O0@p`1=UR+Fo(#UKSu5<%U9ltGswP?_S9hB&%s|vU^m2)oK!b zBwp~0Dx|jG6QvDdrI=!IM|=!Q$6Vnjr=)^YI1-^Af1!+0!2yp-Q$7R*?ONMPv0)L& zYW#Um+J~pQkN6VBVR~EKB$#|{6-H-NU*7Pz=y&t3%5BMW_A)0p74l6h|Kk*5&O-R} zi8Y_}n#05tkcabINdEAR9+or06%zKyUHKI=Yh~tSec`p1a*V>mWuYbFOoXgbnrz+ivj2N0O zV)FW;F4&C-GEQP>JH_;Redf+gP`H$Od@VqGW}HtsnaDqOlY-2NfkJP!pJ|=} zJL6Q>g`=W?s&+}QT~kjeWDR;6sVQ{xS^FX0xihSEn^>cEi!QMHSU{@|o+CO>P`mW) z*VDC(in++wJS)N}^4U^19zo{STH0RHm=y~))a||TN_1y=ygtqK<_t`ee%)2Te7HH~ z@5~1AmVJxmbyXX&M65u-t~Iqff~06zt|BGR8NIBGgdwL~qB(K4qOgodRf!9hyBBw# ze0pd3>F(XubnK@p06vDe`bxsA+Wtlg^z0FBAPQ&+7T8H!=lN4kV?ga6j@`x9O;1lX zocD{YhkmHkrj+{&Apbc-#(4&$GH}++?p&mTcs!`WUY{!-6ZrOE+|sV5xr9&N9N3R| zm`;^JFLiz<`~>(sjj86k=X&F-fl?<1GurkqCEzzZdDHb^25>sq{xo_G1TUifr7Is; zBOu;^q)mV%j;`7XX!4klM9*HOYg{m*+zzLNi2K=J@BBr}rlKc@gvi+avI%-NH!_Hr z>9Fv?__qcjH<{N4b|)_au66BKBXNYWQS;aJgzoAxeshxU(W!lxe!LdMn~6g*T+Z10 zVMLf>Q}6X=t*Uqck(SOWtt|?UR0gJ?jC|r`&0=ch;)Z0nUDa!M32{q9=(B=j3dd?B zE<&*(=}0$iq05c1&eB3j3`Ri2lZ)1<>P=F-qR4}D#MPcXv@>^Jg#pDVR zXGZA?EYY2LGxM@vLoxi8_Dlw4PS4#dlTj}|Z0t`$ z_9*b%LO_TMB0BD!fe{lE9P^3;5@SQ;10Z*B^D7TmDRyeQiMVOCXo;C^eHxuvnSFxX zxON(?{9Wkt^Xs0w^T|8&$xV|emS>G}!(9({OmA70oL1XAw-5_7M9UM_i)W(l0Xf_5 zuxH{AjeIb$OhHULhffeXv1<|yM74*NBtP1X@N!$QrK|d*)s(BQ5Pp4UitFc&T*_$% zX1ILM%ulumxpHV+8$ClVAi`OPhSdqemo7@`)WurE*{o9om{dV!CMWkggP9Q$qs+9!67~LPQtw!sLRFYEPBnU( zvOPkt9IpAf<4ayXTXJzJLe=}#z)^;qt{v?=#ycuXn)1ZR_^E>KwYic~7??X(4v}&3 zT88r^W{fagCGsYuc7k+L)Z_-a7#ghSOm64taDi90VRN@LPec{V@x${y?FNiSigr*q zj-{TLPSc+BZiwV$`PX3(n0Z}QHSktPZaJ+SchZa`cU;0;nh%m&Y2V1gt{L_MNor_l z83{+>2b!38tmW^_LU*mq6w}f>A-q{!^{!|A@xFmQDO;-6w2{+s{$uz>9yb>ZS!+V8f%>3%8Q zHkA7wmU%~)DNX13UT`!&_y+&NP*Z$0RityOg8V7g8!U-&LDyrb7D}{8aW`Zv;5Y7 z=KdNy@%@fD33S8JCEg|$tvA~6Nt(6EY4gFn+{ZliGDjeEy-hgj5zHy)q|Qrt?!4KFdlQV@Pv4Ft5|}$3e#0r^S|qQ)Hm#GaV1|+>?qf(k%OEmXY@Kc zyUMOpoi*RSvcDu3P2mx~fi(rD{XUqC%CvWal|JW{xR`p?d%tOZb0a?Mb>Z<=P(1^h zwx~~w1jDKbWtCOjZ0D}#3~z}{H3B@qQg=&Ci%3o`hIe>u#Ny&sEY_?Y7*f(!DoQ5Q zlyN-N&GM%CPv;v?1n8EiL2gX^!%4YPOfCQu+9r)1kCyJ!pC}-1B!H4(q&A>PFoerX z(>7J%K2TX75^=VogN+P3PI^g1B+KdYv0hIVgV5YlaFEMj&{ma;*Vgh1as``Ccy=~~ ztsM*wq}gd(>tQyyb2J(&GSB-_udjhH>i8tCp4r}6xb&^xkQ8q<^*MY^%}X(K$PkO? zE$05A7zD6b^CUqj%?Zte898ZSqzxMzFdqtS5%=XBAUnk|6cg(Yvbv8sP}`qc=a*L_ zsK|p1ohWGr;KeC0ZO%@7DLDEevvt;Az{-Ko7C4Mlw;;(H1871S1}U~gy-j_2^N&)~ zm+%5iEpHEPNCs-ZlXQxF5!H@6Pwx}on~H@C;?oX#3e^QLoD(Iqz!3B{(_~)6vO+fp zFrETIS|${8n*je@Q)q8zSs>P^iL4t?)^3rem83OAjiQ<-ln@ge#^nO#>!)=mLNY36 z^RL=Lm!jKmLL`NU7U}6RYvow~x(IMyq*PxG@+T6F3#l60E z2%TRwRUqvGMf*mqT5U{ICg?+4jC@px7(b3TutBvehll{T5d;uYPWI5n#JR#Igs~H# z{e~n}SR(m?behMuaGSeAG&)c;zOVxp+QI2f1;_W*ZFbm$eHO2%k_pMMgdt@{gb>am zhRuzy9Unh8(tclB>ay3RdbL08g5X@gG*eROa7~51GF99sqD&jf?|W-HHnCbvje@T! znS}g4s8|rV>U4Ns0Ac4dUC?R<dwj+r{{3jF=`){^d#H4qygdp>3P|5WhW$bDT<+ z!2wcW-$MnaSrd2J34OX7;yAC6AJ~24BW3mJA08E(28#g_(gFKQqI70|}TrUF?FVvQ@NEm$M_Dk;a{ufsb)EPiP?TF>Kg*wA-nQg z=yN$^Wau6(7qSn^Jifa-nA}rT2~!c}%*~F9y1@?K_I90Lvbx1U@BdP;8x$NAmbAcb zNXHg^;scWY)AWn`hV@<#QkD>xT#NOF1Nxewt$^nlA{U7n93PsP7M)lei<|St1QHz| zogRmo<`)%&`|SW4-E03c920cw4*v( zs;%3aD&r6#)(FS(-kht@7%b}Q7*S6m_sdzXHt@&nE;PD0= zTO>;pEItyqwbXD&*@Dm-#79D+)G-V!-Hnn9@W&|X#sYAd)z3!?;1K2@+^jePr932c ztYEILOZz#7fax`z>kgox(zhqxH4Uu*mazD)nuO$_g)) zg8w%kRYH3Yq1(6>&v1GQ#|3p48iz(Wk#{!Pd;HlcnJ)N=?j|>AyGX7}GVOYH3xY$o3_QXW9maWVA9$c~!^z*Z1zL z_w8+O&kBJ67GIcfVZB3Z66#;qyFlzHpUS&wi15v???=*CToy^aFZa370Ol%sjuUsb zIC2CaiGa~)EEXOr0t-cEgq);tAE7^?I`hTa~d&b>>R_#x*l* zSkCNe<0Q3eg>ed{YK3VErfS9vWm&@{wkk)C%4uUIwJM3ea<$}4C37`pmWqs#3P-gi zXVs+1ibl0&M}D<&+#gi-<)w{kG)Yv;*2Q4+qVg|S9L`%e8X=@qHL}$}RhsUy{J~>)BT*=oG z;!@;N>|jT_LAS@Uw%^=exhpdtWml8V|^_2}eSrbpSVnVV9OLN<~|b@CpO%snOza-XEt zBMa9D=bwU8QAw~1dR>|ZX3m-H!J9*mxB=Z0efm>KVZ8)*Y}u|bN3|!-q6zEj0tVu& zFldRMp5A}lB`fWe6wjJnO}lcoCGOIr_dbbh(x9Q@`Ag@`Nm8k(h=6lIP}+U&#HUpk_o>V2>2ab8 z2R|JT4>27gptFXL-=~v?UO;nvhYG*`^Z4Xg<3!T1p<`v{jT>1qpeuu(;RADL_J8g} zox5U(=YWZAbNO=`)t=k|mv&u4#*ArDNxL@om*#D>cZLWb-K!S3Mxz~fGno%hTTWkLAcfJ%&-_cR!~Ls!I!Fzhb|Fw|)S7#3>C z*@>%$@~pG{ZB@pdh=`9NHFAL_@nI105mWSVW%`J;W8C8X(CVY(c2I)xC;sC32C;(d zCdK<&G}F2aq^pJ6{SY6$J;gh|N1(#w_~)tuC0PSA?HZ2x zfy0K>sp(l~xHm7D3=EyUiCh;VVbK{L>Mhj`1TML7f#erdCz9R`C-9ntUlpoFB8Asx_1u%yR@ zw4+G{%M&bv6Uq6f^y`kJ>9ahGFOI7sPS*oO_5Ag-ID zPS4Hy{7m+2rPcYkoIQEN(3IB_<9#2oiU-K=#YjzNMhG;#HTEI>v48)b6ANzflilt1 zE`FkRN(OrtvtJ|wL`wg@RjV$#@-8Q zq#~g$H4*y@rV+UTQc_}-!J`SS-EP+$wV*4&fOraJXALdtiSpRhTXXCb#_eBza$^jI#cs2tDR!lznUME0fE&I$zkp8gs zJ$9}Xr`~Sow^|x2>7tTa2~^WEGbl!iYCdD)@-@}%l8pyw7_L^RNiXHh3HoK>7YQqA zfIZy-XE$h={Q*9NQSNg|ppzTgidv&{MfQ4@`t|QGK8B0>D_WHlG-fuf^Sw#qQq{0x zH9pU42aKDP9Hzq{ExZTu?(DOth3-UUO_)|Sq?<3vM1GX-(@@>~-1t;6qE;{GP;Cw{ ztYQ5y-Nh59&0XYe3#vwCV&8Dqq)I^}eJP!mvzH8vylAVEpklDy!Rur}U&PRPPD7S; z{71{SpE!|@^f9q?!^%gfRnQ|WSzCJr%{8QQJU*BA6Prn^Qm0&>SzTdMzE8Gus2kk} zI#i#?wzCs&7yp26v&nGDF3Byut`q}W$H@cpQz1zp2H3hqBP%C^h0wQgYC-39@uI(8 z=!zXktQg^0U{hZdZv&%}oQ8pZWDg?OtaP8+mECe0?$nESSw(A2~H$ z=y$8Jjj=&(sJxqe#_<5Zjyq2L3BMSihj-dKZLWG>ntSJZ~hsHdF9C*AZJyFtF=k(lgxwnS-z-r`$Ia z6G<6t4K`)-OA6F7Tex%}0(YeOj)i#5nVX#Ees{fYKXShM{1oZyfmJfk%7BEdsb2g5 z`!wQVmC0&w6oGyYF9N9YKq}#h_dWyRt8<_RhIXn(YD4*C`-=?qenp~mZY=wN7}5MtD!B`6YMF~G#QC?D<%WPQpm5Wp-S zm46XJdU|j5z2PsT!@`7v+djrE-$L=IIMiK`4)75gmt4C6u9zl+g#|;7ge{;`*zx8N zfKJRFGLcwtn!!uHow^>^_*6yk-0qT#TNqVfQb^)!7v%+ssK>;2Vzv4JH`EEqo5#bA zoz*}ZBI`N$CFk7@^y@)MY@n^6uw}9PyW)m1g4-EalP4k5>9^D&8K9K;_d8bqq+ZIrSYp2xp%#;OQ;>)I;+@t> zZMWk_OkEm!fD%zX)7j9(C6XHzm@m-`l_%e`FP(YtwIINzYvkrW=}Npzms_6TBGPOc z(=+%^hJF3J*S7DLrOD%sc{oVyx&4STABcG;=doh2-j0aNbpUCkfAgXT+-#pDIy~d4 z-F<7=4~KWw7V?n1XQ_~sA~v_PqgIUe`N$kK^e`%i^R^l7fC9;dFMKXE5P0XCkuwL! zMlYjxI^4^hkaDllaoZ|g9KHJ}0)Y{+{jLU$2S>4T)PO>XvLJdI$(#&?k}44u8`tQL zT)_`g#I70OtRf7FZ`hA)EC%SzPX)=$l2Za_H}-vIfA&{lGPW=gCU>)3DVydlVj9lH zZ0w*39+{b7Nbs+7nQX zyAB2ZheLqx9U1Cmh_tis#@xZ7x?*ibfkD-&!3!}S9bhSBKA>0gsb?)8D=RZ)%hoJT znNfS~vuSRr_MDLiqG={WquL9>C?mjr6egzT$hc~mI(;=wupk0LHb&W{NRpqR_~^P$ z?Sa@PR%uIv7O1*g3B*QQG-%_rDIXC~blui8sU@gk4-Pt%>!A%gmi7+4-~|M|m}%U|&1o^{Y5z`&(N355urh;-5yQPbD@k10ZSsh~yhy z=9br-U!2su?D1WM;tsa4#I6pwqlKd4h%F9u=He;er-iuPUMF^&8t0Z9^)hxij}!l5 zb;x|^CP~~=X8CI?ZT8p+j;Y8-wlyUB?|`e%B;}-qJ<=76B5(7O7D*>qQPROHHg0at zkiHaO%K0xnAjGHYD(Kh#_XSc3huKHOD!O;qt-Xrxdv+ogJQnlgW-Qu-R43@bEM!Z{Z}(3IdTEHD_<~Cz0$179 zDo9r7Fc_4~#46^X&kWei|780UC4? zX=r1)9d%x7m>o5n2+xQ+BP!n;Dlorkj#jZLk#s(cX~$_1(p*6)3wAaL^tFX^C#J&5hPO#g!Z6=vi?ACdO3}J?vFt>U*$l(owg69m0XG^J@o?a0_t>mwg;5^V?4ZWwrDzR z8Cq$qCXvagDHS8tKds~(`xe;8a}K6k&6AKXSBYKjj#t-b7d4w*mbCiyh(KGX>@5l_ z86swTBoo{>mL|E4!Wt13f=#$IdQhkVXn6jD^7+;P9Ft4!iF{Y~DkAlO##B1Q$TmYM$J3HAF|8UJ!e|bV>XqzEhwfczGJWiy{-hev zWvk{XaAkPr&R_bGXXk$?p9=dA@G~?k4nX44#5iAMF|#OE7cWI7993`oq|-d)kvDM0 zk{Fqs4J9rzXvmL`D{r#uu>4)ge{;?JPp1)S^diGv^zMJtMH{$-a zt`5LphORMcVZWqk-!MF z4#*Cu5p9#!aqt5hlj5Ls;J8X3hWpD2)02xT%&8t&#;&boziJC8G$3%_N2HmXj?nTF#=9C2@YztfZd@wsq3xJ_R2D53!PtW*g&D$Ve zZVKW1AQSC5k5E?_8K=C|0P|-uB>2S}(mSNH%laLZ{z77^P{&U=QM(UhK&@?;kZwrJ zMx%JI`kWGrO(=LBY6fvWIn=>gHzy`7jLBMtK+e=_P-sk}rg8Z)`BR(i0mfz_dBr52 zJW*KCl0`Ey%RJxytjsE=HcH3J7(IEP{l`0dZbo5OiEwm7lZAhf8Wpz>;*4Vd3TqbN zS0h0KKN!tnt!hPZ`ye}`?kROhm&g@ z8&M)KdQA-5CI|ha9Y$nW>3k|&6SQV4v&YU}SinPuH7lil0hLEYZAo;|Wch))qNIfx zzI@FWMUT(N-X?SFQ2~wBf;#tv` zhXg@C{1B`(u!adOT9YX`4Zp(3$s<(x_5uySrDjH!EWc@pVP*G7opEay{83Y_4tjjcxCZ1#o&0L3Xn`1!PA6{IoPik8?$5i|GYc=GVOQ9IzL(MO{!MwR zRq&Mak#fEaQB@Ia>jbfwc-zP!tO?wh^=>8t)Zgcs0QSS6a-I;41vhP$@-GcuH~carn`-1{}d0;ZBVE+zd~p*V-O#)|&TxC`kPO125MPT8-GRUI>d z#XVu4+9&P!#=QERdbp30?#aR-SdSIRz3Ykus1DVDfIDwvtJEaV48o#xK5qhq>lq;s zQKFE~eVYY!(IJO_u-Hmhh+Wa6fp^n{T-~_S?uRocE=9#%D;hFoS_4TPB(PE%r2VJz z)4K3EK(hkQq)zAi!0IR z44Sbs5>-isONRAJ8g;ZDB}&(^%m3VfeY>m_3ubC2dN|(oKP)Bj)a1V%&x`Cvh~Nh0 z-cw}TJr3o4fDh#LV$w)bE;xx+jagM)6;IBmDjQFFz))!`X;hG!_olMN*q3QlER4bY z9$$(YoUZpI9j%}5LwKQaI2`u7`llAiKA8qKFrrSL9B+<~vGHksyq2mzL#pd~=t`#E z(N-?!iofIj1-fZYp{+TWsK zrJ1^(jWI!wPfs159A~i_J-8%OvPVaSWhQqT$i=C83C^u*`ONZB1v_!mvhGEVZVIu* zB?^rM;sSBWZnHH)B=O#p&*vLPBEPiV?gRd3heis}>!F;>1oj!}xv&B!77z(E9aX@K zy!!mQ3)`o>M%O+Kc;W%}eA+``-v-GWd@}%_Oo;Nan$cwSLE(2oT4s2z_S)q=;5se* zHWQ@fi{s$zdZ%3!FUrH?r>giNx5V;{`bXH~R3Id9wq0fY5@q>@%O#Vb9G~icYej^P#42o8Y7Kxm6))J@DqlS!y#)8bWYsh5 z>NVfi_DYg<#h-+ggBW|3TJb7z%9%mKMyidUyW%&hiJ>mI$rQH7K6lTn)G2^VK%k!> zdxq7I{0p$y`U?#olZ@vE7PplYI|$)cLmk0qY!RxV>$aR`!3XuO702rZO?umv`=N_k5rLb znukgdOry`l9&;XYINFjRGv?s8?G3^?3h@FaNE=|8Em)bQT^BwFFMvDD%rMN&*Z5K4 z!onh=04?;Cw9C^2yYTc|SJxf4m5xCggZg1;lC4LB$a9(-SvD^*(OV_9)ozHjr0GVi3cN;l zt`2qcIVLBg3N3>Nf@u;`aD5jCfj+zzJ31bOaWP-YV z{vU6pV;6iwa*nz`;E`MP6;w4wl@_g*ew|IQe?BS3d+bhI1Dq(a%R?c#&QCSsFK z6)EBaKYY>-`yCIK|7t0-7tT{a6;*2K*mN0nZfD)f>PGtZ9rns~vtMAshOvIx3$2R0 zaRtVicE_2bTCjXKfTq04yl4^2vaVloE!#<1V-PNgITfu|(^gtJa9W&mh7>sXb;*0{ z-|%PU`auMo|0IIA<69gtWG9)BA0mO`guxWAPHJY)$a=x(tXY=V{=%MO`%a($r-SI8 zO}UWDC`k9pPa~(*lPR)!vvy`CPH5OLsI~XzeHfoo&LJ>Hp4lB@6ZTdt1C`IBxfqjJsZ_O8rW12gt(bE=FvsB`kfPx2y3s#R=?kj2dn6?;n#$xRF*G_o1|$Xu ztEYiwy_^Vl3=Bb)AY8J;Rv}6Wrbu|Ovmv12@aqwB*YV?r&s{GoG74C`Zq^)v+76d6 zQKoCnvG@a{=VcskC;F0BZ!VyFXvhO63)7b?wrQSFjz_dv7mi!uEz)CyKIqo*X7NL0@^ zfR-#$#Z?aPooMIAv@jHl4bQ{L+pQ=n9z5Spmay2#K>$y;HogVuyG(iF9Vp?2hUBqW z09&AkeJb1|gd?&CkZf{R4Vu`wapgqU3aM%7jdEw=>}PfAv$Kbp9TC=!7-N9;adU97 z8qwR*+s-iU_51O1!qO;ZvPg1(_X`qgx5b3GFXQm)Ia9UwOrPnP)kb_R!zNA&8TcwX zr!knK8rCG#%1EFiQej<%9moguTYq#GYOBt+{UA(+$xjunf4E9VVYuiD`DN->Zl^~9 zIuCsLHW};aQA80>Ft@-l~CKzFp}}J@mn$;8pau~4ZxS8V)GuHmV4o5cLq5m z0464;-T-Z~#~3YuOk(gjfvH8~4GUq*nrarMnK>i7$yde6@Px%3j0xP@>I5 zJyJN1!uVFUt%#W;c^4_s&Y`d8)S}SQ(wtg7pOWf=N%{~TnDHC=8w7Z`G9@6#jy!q- zsUjUMtUOufx_{l9DnCp62q)=)_^ln(#Ay5_6vuD?p;ZG&LLmPDMPlq=qhtrTGi?{{ zSc<@IR{nCV0(lz1=Fa9}sGe6HCu{N!7{HvfNqdwYjMfkEG_I8XlN~J59&&PS^@<=X z_xXESu`FC3x5&un5UwjbY^V)R`{S>Iy0!tD7Sy^q*Uiqd0S4uz9|7fx#OpbJpxq2X z=>I1%Acvh8ly6bzfo-3~#lqyqxoWy5Jk6X0`zQUmH8a&REXkFFX2$mMu6?xpkQiD! z?CC}&^DsiE;_$2wO)$5IhxDx}g| zC6`%uBu!Le@Z%f{ExlXq1oG;f~%G$Lx=MK{~ zW`j$sRLkJy5Bx9{oqjD(`RR65g0Vxz40$o858;b%gqpPd=Y%=wvHgK8tnze;>Y0C4 zLx3xL%ghd11Z-PMO^NrVsWJVqQYr43KR@GBa$)b)!-f(nj9WNy2qQ~LQo1I_J9g`g zuyP`5j06>*W;Sg}3gGR-2ga3Kp_?c)L81XXrkcDMFxnXUJ4l$FO5Hea0+G?&BwcW> ze!v^){rziScGf(-5e&P)GHO^W#-)Jybj=#1WX445d+ST zJ%EklAeoy)9)_W*<0(NMp$m8#D`8&$J*a~sjY*4|ih2i-L5qfs=n)%IQC!5|s_p!b z`b=++angwd+(hHm?91^ot6~%m5Mx6?+Ck*%;xA-5<+gJ}^=w!?vLLvHQsWp#$>e0Z z)5Y0p1HySMHlr8JXToU{9#b?M<`fvrDR8MilVk1=VHl6|I}8PShto&S&L^p>y0?Q~ zc4(^CXj2zJ2m_=b=CZ?rulm&;DSP}50NV#;6TOUo_WrqHAL06$?jMF1<4eytvhNZy zVhlo3$;Efo0rOFpqe=!h6!^BXS_HSStSzwdr9-8RjxomJ=I7`uK5sQEYveT)SQ%Hd zgzAt`S*jUjH+L$&M1PP1c#08N2@6a_-GLZ_hJp15D87f@YoEL8>FO~qrmm*Ajg}s( zx;*qP22%7i&H#M+`S@V`7DXzQ0`7`MW`(ND*bJ6S9j=j-O4TPb(^-x^j<;>6KBqZ= z!VEXwA4>O|8X=Y$*rEJ4xM{Eb)-^91w2qql6HU$2l6U7f`$SCfhm#!TY6a>W`;f?C zJt+~_yw;Nnv?!P@-I^+&r1A?(4xZ<&1>o~qdL5F`k##-0z&EnqESWLrQ4M4VFy5(3 z4^5GQ0X1!Ba`;HNF~*%ge;Gr@S@Jw5`f`Xet@5^%8hekd$SxXH*;2B1e9q+T$)0)dyW_gio$EX=`+=K!q0P;RDEJd=UQvxwYZ& zdKUK9RuuddR?;|mXq%*j5u?JQu?K@O~^#Gpk;Hw`fPR{XK6b$bkhuMCMssT$LgfMaqEBtAiJ&wtsZ4 z(dtFS7>YN@!akF=#N#c8-v45cLrS#L9Pvi984&LN-s~}efXTGe=U8UkBArMC^&Im|!9zC}b17xVa+Li9RHZQ=IhBj`2+7B{Al~!6(FS zl2;hMAPnBm%2Fc~u;+ue=2$1ehvkqcn>RNB*}Pw(KRZq&@qd)PLy#~`w6xi_ZQHhO z+qP}nw)<_{wr$(CJ>P2XKM^-3W|pv33i*4UR=~uL50@!2PD-Nk$w3LqT#XLXqFEz1LuVwr=As4p3Q&*Y z7iaa#@Ryzg2YS~& z1n-Oo@Hqp{_9RYvyCO^EPzRrGOwdHgz%T6sI~hqR_=N&hYZ1mQZ?ut64SHNQz?%ZU z1<-Jv>s4&^Aue0aTH0W1tx{w}zSXVuZhsV&GObZE$Z^BB)mLs32Vzgt$Kvg?lZy*% z#RSBoYN6ro?qU_~ts+`rtZ>v+9M1{hO`w{hT!(+57TgdmZ;ruk!lRsOPhbuEV*&Ua zJ}!0W&GmE(lI_LaPH=WILt_9Y4TdMv%K+_Me9QCl&ur{B*uY~iFadSNgg%eH&1l4N7xQsoapot1-1mz8qI@^?oipZ;*Td z&`qRVbqQ4fqH)8dY_pRot;)1vpjM2PAdI~lkZ`M_&H(@Y$D|(S#Je(vNWW4={R;sF zDM~vZ)=+>#L_$9`DL}0(;mR~N+C$GipG4i7wP~0w_XTX5R^5lMI^<`EDk(CkMS_2@ zj3za33=ETl!1%H!XJvbT)Qy!x} z!nt^Bx(%BP!QL!hj=T+EmvbBG?S^_$=|h5bL1NT0`9^*HbW&Kcuzg+#>)@ohzO&=d zwlC-YYE>pFsYk)xL|O;NFA>w?Het7Pw%@J0s4y#IUl;Qbl9AwA;^cuG1y>4gjIk5H ztgP`U__46O+5Mzcq{w2OwjJW)DxHnj!{!@pOn=2}KJ+C1Z*2&LCYNNtbIg7p|AJkv zXeG4vpOTqSSh*+Mplg|g111ImM#6*wBMpoqDY5HdX03H`H5c3K@c8w~Kls#`UkNwM zDc@4naP{C<=o_Xox5K|6Huj;(I_L=xEAKS%t>knz>GbP9Xr!NT`Ah;!JOT+b0m7M5 z++`a*wQW-6wrNeJuh=^6{nAvW_jei9>%A8DARaRND+#C5X`iTFoA9XmNy4Pd#_+g=xxu@9F zpn&YrtEScG#myG9!I6YYD)BppF%kfOrgujXb@Jj6mBo>2|`aTEJuGO4X<_D3|3 z|3?E*IRVYS=mG5Zyx8!A+(hYtyI6(x%$60Awd_0b*ucW5)9HF$87_AF21uNh|A}eK zVBW1cq$LVnvWvOe!^zj>6(^5Y_3K$$*1{;!OEtTfT)ggb7^&y<8Qr4Cyn$Wrm|_X0 zk?jX)i)g8&ccU!LNUYt+?t}>0TzPM3mPjl;iLz?HwDC+;>nE0PmDG*=CMh}V&c{X( zO{6jYrDN7|)>ZCkJHB_IY00ZCwrLYNMu;#0^io|pIwv=Gg&Q|!XLVwfBIRP*2RTm5 zX--I5Ou$atV1Z8jGxk#c-hV~6zA1%M!GT zG%SH~RZZH0z-kc*0?2n6Ata>6M1-IK5)f2dnrK(hDh(@Fo2sMs7~51UaqA1%o{FV# z=x6!A9d75-?WbJlTlZdP$|^?2(0!@mwDjP&?rr9skST}1FuZA~a)e~08g8m@A`~Jv~IoGGg3+$8dnS%1l>J<6w z>N*B4YuVc05M#!vqa*dP@$g+^+8(UF#L|rvV8a z7rNTp@~|l`2o6_uKTP4zN4dK4T$fC%T(*i525M~*`Ql!efe5@oF?RE_g%6{C$HIs? z2wST-+UR2`spt_g$K*BZB{xMS7P&)_gW*%FW}Q^X7z;az-l(+fiA`SC*h=!u@mKSM z#`B~Y7a<|^R?l;_A;gBdZ?tvq=5qo|n^Io621N-|hbSn?AKI!r2*c9s4D%&|O(3X#zya|#Tloe;Id;$p*g_UFdij#VZD3J6*4AhV(i1{cN{$`T-g zXZ}+3jNhh#Di3D&F3#kfbS`s5EPu}n1AY4~%S#HjG6p>{378WygO+)vGiv3!OZ^wH$aX zHck`P5}Mb0qxCRzbdup?TR&?wa;awCC#lPkW9TifMY-y~%`K4)%314rD_C1|IlZg%=9Mj6*O%%*YA{3Mg?eE|=tBU| zAaKCM0{>8uFyeQ3|>;})IJfc*~Cw*?Y_;Ds1I zmKg$ro7EIefGz$XhFMH0r(XByR41y7L4*bSK;(n>qni&-y87PWKTqn5Q&0Juvd$g8 zFGD1-?D-TD6uh5P^o`{xia=(#0~&w*`;WmlUq=!zPH@@GXpV#ij*hHLP3@)@vG?Ob zuGpbk;4m@os*!`6>t`2Sb5A&!-B9L8e&z#dh&d1KW{TWMGrlagNA29XCVcPMyWnJ4 zhR^Hy&8<3p&-)Y=&v~8An8(s`B}27REoy z%XqVHCA|_Aq!TSq*Z_6Lmj8ljRTolGxZ($%e!mE2 zgB*N$m$F5P|2-j4pDpp^B`3C97&181oyO<8S%&95k~6dD=+mfEq*5UeC@K=*poLmc9bN-GL!z!nH~b{>Gd$LdD0WC!FL`vR z=vK%rXiRT9g#D&0U|{LCs9n!+i`?9!ZI*bg*1N(i@&hwq;)C*i6Ps12WosXzFeZrJ zAXi$6nqV>?QrmFWWLK2t^!NyKT8qT$iKDh>sYTiVgbq=9GCn>s9lVE`Fu z95(t<~ZaU ze4z^=!tG>yc)BHEdoeKEo;_Ixf)KzzhDd?1IQZgB5C!Xt8`)3hZ|#_VoG1x zuQLlnpWus3ylVj78j;TF#z0W=DjnfI{pvZ?0gLj{LHbgqm~upIJKa45d1@Pw{8tnr z<0-Z#<&VzR>DL$@tNasx?+^H58)f{z*cI5A{|CkYf3Yht|3B;s3cU8i1TZ@vsCadk z0GvA!82>ef!u%*W-^lg;==oPO6lQF1XLPYNq z3uQPo!DTU@S1Tc|Qk-D|m^n1mMw;zm#^WG=CPq(3Vdrp77k>qKrnQP$m38Q3&DYPw zSVi!25K9jTL?~E5*z6s@r!oi8GV$NGg@!oGVjnZ8bA(hfOtBN%FGlKzg%T+HTN^i3 zj}h~ol6cLJ;cW?Wh(*=UXJ)HDj6>~y(mi$V6V~KPcfBK9!7_f;w^y=73tm0=u^9+I zEaQ2k?gyaAcbxg()Z+Lbwf?^w7Z}+XnEwysLP(OO3W_?~*j@1jY`tc73076A5{lx! zDt&+#i3Zjh26{@lWJLKslng*3V??7Q@i<*{wJpkaP!V7v0adxq&H?)z9{0s-_Xm69 zlVE?2K3NCPuNLcyx{fheBTc|@0XQjzU}6|xa|clO`5^Z5fbc{HsL_6o3;;p{0OpV( zlZb!{23)g2oD6Vi0;nQG&f$Kki13#Lh=~L+Z35&*L-6YmBZ_dUb>P@~bgg}a<^jj^ z5WDkGzIF)peX#8?z;{Tz0p)k}Z@9XBR)m6kz=;GTP9pQ;xb6hFi^PD@0s)j57zz|w zAw&rw=6RfFO0AHh1*c{$sKj~_DX)zufUCO?Y5x#zr@>S348f*w(n} zlEfF5#!|7>6^p5QU0E7)BTnS0OpRHSt*jH7|NAuURA@sRV>-0q&4EoCB8xH@25I^p%umOd>2?n28>t1rxn8Iipk=TI^#Y(40A_$5 z3kR?a$aM~=Z>c~pPy~|;D4|x=)ZZ*{2GFZm#20`Q@(K88a^B610?-L9gXSU+7RvNI zk0%Ad+Ze1Q&__g(TxiY|l7TdSTFL9II$)#9sE?b`AUCZE+q4?$c{MuyVsPsfg#NS! z&T(2#4`YsZWeDQD0Uy%mQ!D&BZggg5p2|6~Xxh?fw=vg9_=WhI_!{{te**R)^Z^>$ zRiq@CikxaoRn1lARjyVJ+9JrS-y_Mpk8pM0@0eRW;y7-Zy)?z!$M^CMU56KmX zjucX)XtCU_$S$5OUKZzf+c)sn^Ox`!&NyML7cYzZ#YDikzucbUSO-3@;?M%#{x-w*yk=!1bjuy?@b zgMvSF^UlE+*f)mTj+{TN`;Kxu%D<22gY|aE{7%Cc{^h{W7f-(*{VwhUsXwZIuj&J< zKgND9>jV7O3zyI|tjQd=~gLyXW<9xwArGDfeQV|96NhpPHYGcREq!CF#Hd?Dgv&cE*z7P-rHk7$WH zi7|TD?;)NK#1a*qW#T`1qC~}+F=}*qXg{PEZ7}&M^zfM6Dq?H!p61c8Ij&phv6@`l zwJbAv*>U-C=|k3IrU`?;X=roscV}g!ZdOQ_n{%Yh}@5JBHaOh3{TdL>$pm0A~|Hdv!SduDUm$8D!Oi z+T1QT$FIdpwi5eUneoG9a`ag$38k4>O?2dnFQ=i2+iYI@h%xD&Qdb9}j)Icf=<-A_ zIxWXrL0v^%N8mke*UX4vJ@=tbgUGzyVtots6gJV`c|`t0Suw<;qjGM*WpgPET)djS zPBY@vy9jknHtj`b4yYf=zuVht%IiaI>ZN37sK)gVO(+^PJ8w-pO;1ltSwwverRK7< ztMzrBu8^{F9~~&igX$4lQ*ck&Uumpr*}09pRMjlqlE1Q`cYc1EoVb!4Eu|WL72zFP z`*wAHeQ(97bk}AxoHbWmo9#AneJxED&4HB@743K0tu>R;vyl^1H2NuJ#kHE{)Jn=z zA#S92lgBx>UoGBz=n_3m#qQGFVVo7Z@_6pA3}U)DJ(ruqtJK1+@~%KI$H1~7NShP> zvV+H<@7y#Wx?--f*4_#yd&oU85zfeJl3EdYky}-rJMkm)`F%(KBS{v?<-FP~WNt^u z)bnrIPqagtKHV*GKHu^snAIes#UfjKQ}il~{Y4Z^q}U=bD($*SU-bE6lR)=K64fnc zl!Pjh#+Q(v>O_^;D8NZ5wU)=$eke2wRizC=EKwNDHdV_gh@#S{SCC)dNhMI}Zr*96 zDkO{sq9ALP*FsgVVD-fI(qJ1c;`i3J9Wg zKuiL473{oC@3uog(FQ~j1s7DH$|*2tIK;5Cr-!9CwPa-%r#Nz_y<6`#FTgir{JDOT z@n_$Tax(9JX1{pmzH;7p&&2%B)6R5Zf9%oovuRbXO97t_=57(t)VrI2 z(hsfRs0E{z3@6QccL(;lGK>PM%W&5JK2OeymrsOmSt3kQNthwbE8x$2>IRVJc|%B5 z9CKbdXGL*;anz5jyKx~s?8hvvg2iTPm_j>7IkOY#^dylOk^pHd@En?bzir2l!nb$& z6s$-2Kd27VF(ROc){Fr1^Sw;!ywcfKkn+oJ6&fOFSyL`1-_4vbkuc?{7ton{Hq)+& zdIk#49J0z9d1UiQmq0C`Feu2;$dm16t(_fDsiGIAg#*@S`k5Z%17){B@GVg5I)XJo zACCEg#VR3uE*Sr|7! zs2}ichcF-h{qj;ApeKMK^3;b7a0cd>6Q9=09tR!Slu1MRnY24um&}XQ2IWwafTw`J zP5gUDi)`Ad#|AwSky9kk+Sv0tWfYT5RhuH6a87dh2FYYHa-ED3J)`;pR*MLZ3ED@V zYbY;~oJ2Rdy5LJT+t&PIbYDK@klLb45#&8?nE6*%cw`cf0^+plr$C6akbcqrC$yfE zT|%93D3nxlVTEcHyFykQ5#dc3{=$+R&yZ+IbTn4$2j-`=KVJ3*UrSqN@0&ReM6r@YTU5h$sg!(qs( z6{7~Yi{Ok^8^@J13SbTWWCOT>!n6}+%!!#(DpjNY^j=C{?32$!eZV<1vE(%JK&PF$ zV}fkZX<@KWII~E)xlb1@C=jhJ)%!u@ODSqeQOw0nF5{Fg0P>5BzfVCNms~d>1bBo^ z8K|8mu^<=!6%oBpjaKTy69#(Ed{Ooi2@ZOxMvFSJYG!A9FuLe{$l$?A*PlP>5uDi2 zoE6vRe7_3*c1D-fgRCbrHt8_cUx9ehQ#e2J(J6e%LkN?5Qo)bmh~!zyICXL;qiR-c zS;TgTe922gz6n&S?BB={T22{FJaJ(G~Y!(F_B4u)J7?$Jf25df$dO+-IZvOJBV1+=13MR)_8s{nM64Pv;#W zcwf*x^${|J(6Gt_a%=0|^n_p2%EcefBxO%kicls6Q{V6q!(FD5H~w2&Z2nQ0)2G^_ zmCyyt)z-@+aOPC2f$u^oo04ds5r1Y7`;$; zPm|ko=fdf8{7l8T44T`Gx_vr*`oVGwIRCQOR{^Zi*Sd1Y7&DWTGc%K}XKrrot6ZL6 zOTQ4VbybZD-fF4M7VR<$gYbV~_cQmcoRe@bl_Y+$S7&o%9h-J#37-PE6NQl|X9!a; z(j4%#@iNi_AfC}DDIeou*DdNbUC`U_50-N#TCZHUU@))K_T;z)3XYM@Gt4m~BnyU= zAs6(MgA|NSNWmTEwouW*kA;u_AzYA|_>tHsxz09W@9bchMn)jNW{+JeO`YJz!L_4X zE{{&S@j=&|3yX_npPg7EgJ73)tT|6Y;+X!I$AW*#CekhNwp36fa@j_c2yz2}8ktuB-Cj&_jFO!qD zgy%5c)SN|vv~Y2;a50hTfnwvY;=S)Dicg>Sy`ex%i7#Aw$yz8YBX9=0UZ$#P6JMhV?k*<#?KuByOt#Ezs1DOBRygf(l z<1Nj92yR4npE2$1tW?|EBZIh&5jO2<@z5gu>@EC|DMq=r37Q^n{%>Cc;#r*AoEfhb zYDcxJiK1+G1Q7Pxw4EYu9Ec*bd0C!eZ)rTCZvPHBf zxfxmty2g}~bo8`zkYn@mDMk%{WU235w&a^Ql%naVP*kC+JWtTgiFm%8t8M=RCZp6S zoq3n@#daduyv~4hLx|uW7mpFvJ)Gv(3}BpdB}qC>)MWJ>;KFza(JbY ziF0k1tyHPUrabhf-l(Uxxm~_O%{r)v&z`?!YWTQ(yL2<(v7y_ z&)noB%v>bgwxOkZwF6rEOC$Q>*H*w140#pm?MO}?KB0VSGgbQ`!bqmn%x3z-undRr z>H>ysukCW$z<%5I7>=WTyV(ZKVf*B5u`A7CEqZ#QlRR3S&E(M`8N-8;&(xl zJE6^&+yVjwT3juoo6hmYR_o&jAlX1JQJjj;VFppHuXbV23%8| zHMFg(=p(i4x)p^oP}}BYN#ye`o1=}sIgO19+JkdX-I9R@jT!?6^-(aFTB@=Y94pAz z`B8o)ri`e&$rOz;6Q@r)EfpKLMLnv|(`TablAl;n1ehxIi743wrS(=UVli75+Y(6Vo)ez(uQvT zU6Nge1Bti#ckRP-H1#G0HK6}$j5J{ahim_9$fjmjeN1)r3_(=uc)&PnY_HmaaNwg| zp>E$$ye_X13Eo3G*efMp;r=vt4%xraPUQF@_wkAg6)Q5t%n@$xP};Dhd{p7; z$bd`K+y9Z$GfYHl+8F(UubPBjWh~mVo$~i#;sACp)qeVfjoWe)_fSWnBmx^6Cm>I@ z9--`JU16OoOHL3G>M-DNaIajsY>t!{IU#6s9dgO{UYmBmEQx;|v zLZK-k*if$^`qQWjk;IKcHq>V+(JKfWe|Uf?8aZ?jM4vQzCKR(PFpz*y6mE$HI*7&% zno>U}3k#(_N$K&scSK_tm^G;R4SnUQeE(<`90Y})S6$*@ag0I8qbc6=9U(yR8p?-1 zmhFfWTxYBR1lE8NBKX4q_S3Ell=A~4Bup4{GS+;~HtjbW%fpX4y1?L#MAsQ>NE2pg zK{1;*98DVo$PdxUvDiZZ5jDnm&owp%zI(bzHBy~G;wJqt;H>-VmmJQ$@p3+<%pa8{ zzlLLJE_c=mZB93`cHd%4g6pr(sh&<+IUhp9RNtaB$>FeIcJj}R5^QMeIz7J6b;ViR zN6iaM-_b#bq@s5b1lrp!8jjt~D_gUziX|U8KL{ND`~)ujUpnu6`I03IkfO zra6gJs*gIRdUXP&Nwt!(^CgFD@oQ9}*Iz@IJp4engl7PVc%6QcT9iQw)yo5l8&W>* zx8v+G|A@}d)y&n5tPUi~!m7*G*NDtx+P`xRHn~4}_?Vl}hBvKvv`{Y22gLHnj|EWN ztT_2N){H7i_geQQF|!g9I{Mt<8vWwkQL@Q7eJ=eqd)q@SJSB$0Vt6usv#yuCYZfxS zMjKP6iiuPe^oEbjOB^_(s*7mcbh>Th+hIJdpu156l&B{NIh zI}8_pTB{~6@6C--E6u=CDdTwuS0LxyirERAgqD9~r=@nZmC_~LD4|+Jd2nKWv|a8BxYoHH4=|rI+F2RN&c{>>e;*{@pPGFZST+Tw zW)-?p-PruGE$I;shB|Cck<;J5E5Hl~((kAW47lV0`U8|o2P>XB(*vuct4FfjNj=H zY8Ngs)0&FvSCy9aNka^=K{==42oJbRg;2A-jb>u(DOFCAxJ8QJEBh#;&9ddNSikI5MxWG0+)LzJK*Iv}Rx7RJ#}zrLqm zN%%%-r!|v`nagOn6^Jgkd$x`Z;X8>>9Jrs>$*!0qAJ%E`ah3?w%FAqy-YRus)%a-JZWG@tE(9Tbr!7{&R6?08 z?WW9$)u-JqErnM0FH?}!_SN@vt>7b9aeuo!T$bR#f}98nI^1dTqU>R#x_}9Iy}hphP;o<+WF0}>=-2vG z?dXe~q86?zrb&uqW2Svp?atW;|5PQcJnOR71OHMFZI+-a6KRaAPumUt^{~7?|8ZXM z#EMqk6~u)RE3PdKAn{xibHvR}&QDGgi!C-H3Jvyu;mK{EJaBDj7D?9l%OS&aR6xSw z2+=206A_}eQvlWt_Qmz8n-!IgdIu_*JY5_7{AGIH3iAey`18JrV5@#~?776M%TRrW zY8cl>UR`1&yL?m5%P>Qy4zO5xE-E_)lxDa=ay=U^o)XlW)KpK_@61P zFMu8fLyKjC=zi({x?Z1*f|n1iHdI5VC)%4G@sXg7Wl6SWbd?{r-L*7PfmY_kKiy$mk}6zn*6g5lzwCvsqkn3f3zDaq3#8 z3%7-ht8}WbIH&D)!EJWa0E-JG$4a5-1ZAvCQXmDH=AFR;RP7#Mi$Os2b9{yF3rE2p$p) zY)%&=T(w~ZDkT@Im!U34xt!+)e$?D~J~b}->?{}alIOVCi6*3|T}4-T-^Yplfr;8I zEYI-Yu!#)`&Fy=W$Cv(%^S-!_K675tZlN79sH8LLgG z<~)BrTc^0#SI($R@n#%go$oy^|F4Wrww?Zi%#zKS7OCvu+MNO~D}2;GVZ(MINfL^* zUiy>D3%e&aGLR`Oja;YFVk-m40mu)~dC|E_c&~rxVPTA1PzD=Sg@P0cHzn0d$vGfM zkqIk9Q!TSCn5vwED-Nv)eST^!+|nLM?$m!c=x@s4N#XJ*yZ8()lrWm7ca$Z^IU?511x;WwyP6p0C*mPC#{%|leB zq@!Fbeah9jI!(?W9QB@E^7>h`8#Fr)nfWm-E-q(?Gi3R6k5Os_+{?=XSG>4(Wm#D% zlee-sIRWpaSkmYshE8f>Pck~VfxBPQPygUAQOTiT?Sxsa;h%}hAWnBS1CifOm z#To@-jgU3M-p00>+h9RQVO12Bij;^{)na9-?g^YB>3HgiiG5f}k?wyFH7l2=V>TWQ z?hDnpkY)aaS1DO!sZmu66eg|$)(fo`hS94v5ar)i*%i9R^IJ6BORuK3gU+$g?Wbl< znE&+C-m?sJEX~7Kw(WFPRNy9=qmwQTgA2C{K(xXaP_bROx%WHHQv)gID;}kJ8O+P| zdWw^^k7^%Yfx(aJn+N2cvm^2AbdRxw36%r5xKW~(bj>oG5-O*YB0^khc5KqP+EwvV zi2;D@#H(OiH?P^`sjYiSB?351!~*N(BrRRwy0&~%RA0Z&!xohOX|MFN&sa;mFBaC7 zRIM7B;U}=2`8t|;9DeV|fd9eS6SGo{N_O$iAR<&et)OB{!EO-8^1{#V2uy|T&n-#I z*krz8LzzuJGYuCcE<^+h(W{~MoAAg~*VSd_kKBHFpUZwDcIdPDI2HYE3cH5w$cS5{7 zXv)u1NJei`Kh(6o*OG~lx+%-H2#yVvy;S%%&=)yPK2cXco$n_21hteLl_?(%a`hJU zW4Md9@07=R!qnm7u3m)_@sXK?`77+*9LnOlySH(dBi3GU!-GD%<`fsbT2{@CYU?a3(L+E$sg7bWp@1aO z5hg$&NJxP0$kCAmB7~IeCy1aRpcVD~cZgcqswb82Ibg1an=5~%)8^}_-)XLYzUlwA z_PfsMpLfQ+_tn+Y_jV({r zGS15mcK5n|G5+`2-#mUs-wH|^B1675ZVB&)W@1c;Ut2TyiM=I7qLnKrJ*Y`&D$Li% zA&p#9J1hWf_ha8wv|hh|7`r05zzoP)18U7@QQ!cud0zP@pdIOTu56ggV7uYxc zetK7cWgF#_AObAp?j;C=xd{^*g8etYvW8pGuj8YVSzxmL&e=a!c^`DSxJ?7q8+F&@ zV`Q3nd7mpNJ1?OF*%R4d#hZl1>0=ld1_w?&HnU5k##De4r-#fF8|lb_`go_6sQi;} zkiFnelfPq)PohmzizX5z0GAaQalbD-J6n5%VsOuAU6E0-HpzMnkI#64O`9SJ;`@%lK)~Nv z`QEc~Zwgi0&;I>8Sfds^b!OyQE( zb^O@4aLRVwMcUp8b+z&l8v0MGZn4th{Yk-4n68iG=?kJv{%IuKo5rhZU@%}Um0+=SUOR5q>_96qtx-U|yeDCM3@cBvZz9FlDFqM-f zs}!};$?Sp_TtMr76Rh~bDIUg|_XmK9CT?kPOX9vZ`5_q0vP(w9vRuSqrKeC@R9|A+ zYddSRk}7E6V2d9s>MpY4;C8)N!BY3n^*&-R)2>;&0>Qz-+;-d*a_{K0Gly>3s(KjQ3Qw4rh<51{DegKz&}0>bwb1#~WhiC0Q{}dzq_QU| z4fB-x1476SrRLU0zK(Z7dTkvXd5TWPjj-q-cG?Xwfw4@~T=G)9l?nWis`EE_`t2dT zBR>s;c&{^ZNdAKH_D+LS{vRIm7?|3)OoRofQ9Ir57b86()?uQ3^Bwu*qv?^QHxrDt~SmnqzDa%J8vw32KvjIUsoybAKTJ7r3daJtcr)J3U@Ti zkgHj7-rbn+nJkaPrn<=czq9wrC7S7ip9DoVFgpio962YD0rmHR{Y6`|+14(sXO!X= zEtEMZ)SG%>Z+K&4JCqXt3~^dG>Al@G-hPp<$*YGjE`O$O&j^4-l-$Dgtj%eBBZ$>T z(N0Pk8!9~Q?FrL;dXT!=mM>T|EUpOD=uajmDL8^pc6!6rnnS<&)nu`nCul+zZaXKF z#JH{75{bM2EB&>*(yNjZ(GhuROLPoAY>>p~~zb~1GyEfC9%2zoT4pH&(wwLtc-`(tMha~a41H>r|fQ2i&NG+r744pf}RqcWva`v zH2F(hgO6%dM=rZ00xskRK5JYPqxMr3;JuNA?J@qlH7`CZ;~SkBkxDO#vM+q zz=+|$$4-IctNUtVD@JdaA}?TtadkY0mRTzo-W0yBeQDQ;lcV;%yK1o#+bmC8Nmi;FrYf;zl_dpw z?AZ>z-wR#4u~$~b0e3*|PAA)+55a!cakdjNMi{0cIE?5Q5Wr(^jYw8qA7^9RY{9O| zZQk^VmZ_2e!3nc4a>YbN4EtoNvg#`3pglQTKwNN*dB=n1K#YM^X%~3`>p}rrq^l&M1 zDW?e0{;3+OEtoA}qp&>A|D@qXTxxOMW+>ZO7*5i5u}o4!_|Y?HP#;iuJBp+r$_4op|rSI89dZ8`|AeB3apH5Ycw!)E~&ZhA9nE zQNq4SO%+=maGwNP^HOlwN}$}#$h++M(FKwZ5}dN{4B((V2&k*Tw4KQiXG-U54g2ZcVxI5K8cLJKG#@Lii1gZG7~l$_R0GJ(hJngQo^6> z>rL#|lmY7a>hLL2Dr)PQiMCNRZ|2@ioX6u#@&zH1=`lFAz9$;`)IG6znu6j<<6=Qj zY3B}BFY7fK3zuGV^sJ90luyP9g3x1Wx!sk2BlnkfJ{T?>K;c?r(o7rt^&^~k9R@C> zNLNelAs$!ktu!Uq?kk?s{~`zzZ$fcS=5syBkJi#POIu#ZrjCm7*L~JlLwvRFjCiM{ zr+<`F;n4DR`d*!RqB^yt?lW~q-C8cfN&kuZ=d{V*H1H-va0o9xzfpM*mE?Q3+)m;? z9*o*qN6!4u#rx_%%kh*kFJ);rT>esI+K<8$<8+|9A*jm44Q^44_i$+-S8Gt4mPcf| zPL5GThHUwC?SJ`2)-+r0SDNN}U-Vd@L%=zs5k5&%5wFe7^-+t5xZvL_l{<+@fVM( z&mSb!K_iYnjQ!hArMnaYQ>_W1#~)xh&aigDsg&WM%OcLM>7lHVsV{j^N?xQTNNBY3AreG%_?Q>7_F*8>bhJ9@VL3%tLhk2;! zNuVirg(Ww+crDyyVX}?%Gy$K!f%j@9}7q|AVKZWb-0ND}i*v+Ge+MKCr%K?=I zhF@Q%Bc+W{=&#F}XKQ_SOMN{~k??9JP4d6I0(^@`Oce|^QjZ-Ip!8yrvM#i`o1{~M>x{y&`d{~OiL@PA<0DhdO3 zLj*8APpEuun}H-ti_nLQR!VSNm8Dy`LCA!x0XRey_F7V}Hc;t#iJ>)u&P$%~FXJBEyCvm4>^ z%b@s7;6EC=0DuARChbK27p2%4{zs|*A4EGlGyDG`or{XOhKe~Fp22Odph>xV2)6^h zE|?&oV=%260wOA^gXq6Vi9|N49?3Dl0ibah+GirsL<|rW1Zfoq;MQ_RL8Ix~+ANxE z=F@$%vFrS6zPaD8-Mj8P&%7tUJ9iZh9o4v~sHoAb1P}SLmN>d-UH(B&s0AHDx}gO9 zr(JQxwr0Fb9Cj_8;;%lLI4JQG6!FoMWoHgr9J!W8)bJ@n&MOYg9LrRKRQSr8O8v^B zO`#UQ7H=zN9lG?>O-JH(+igrE;zTi+q|JZGnxefY3q10AEcEH>V_%W_{r-iwWxJ)n zb)4X5JZlT^A%6&0Q;Pc;S&`^{+b)RI@Bt+8%-ueiA@Tx$1TX)(S=rOAaLmmP6>x%)UWt5!<3i zVtiu0qdG^tqhGP~*ng8ggUyZ9>oeE9$*5#|nVng;?6!~ zQ$|y0Q`l<%Qma(sSGqoYSO2wyzGzwNTUWGfd-Z!QezG^ja%j+?>!b3c^))7Lc5CnV z7R;@#y_VCzQ+7ueL2Im!kOc|JoNO7I3UCfgj)TzeyM(e_@k6J zW<9xNHoMz5lSt+ak`&k#>4I$Drx!AkCW^Ydvn;nYOJEfbCKDxN47hsKXh`Me_d-yq zx~Q6+9E7x^NWvwfW`iM{!{O)B5G{9R?YCB;}M`AYmWM~NR1u_^xci;>`p!@=6 zBxddoQ!irA{5gMTKeFY#C;7k}fI$2Km`QlAi~1f@zTkgB6-Xb*fVPCXz%0Ghz3@z$ zemi7w<%z?9xr=u!l*fN=fJ0$gsQO5Qwt7z@OCP(#4o;ZB1A&sGdk}@|`I|qf`^8Yh zZTO_Ql3(>2N(s_fsha5RvZoq(tOuSGU6n%KU;LeXk^la%y=_!Egq+KCq0pC_hK2|r zRzUz8UnV>ADGTrcQ||+gHE;|pgS057dSXcGc0y(Q@$BLCE}0^4Zg@)2uQ3-CwM*ZS zk|O;HkT3iSm!MkOB;|1AV!1O(g;biAhwFT81rGJc1y2Qc`gjJ$%%rLxzeUutsH?Fx zj)cD7217X}K8IRP3UjHvJyL4y)XvJw;G4yh<4s8v$?}QLl*9-$2ra@ptVXr!C(apb?1&i^Ye|r(!%B)%WDnQ<%1i_w{cMbYcq2rWp?)0l! zahktCs{RPYL3Bju$bwXv?vlGmaLwsa%|P~G73pf{s*qZeRYx|x#py1biS zOfDS4MkgD6-S9k@dz~DFeps3L=_B&o!o)!Lq5b?Ep;d>hDpXgU?o!UK_xV_k@i6Im zqo^hDb#l^Sg%B~Ft_KIxvEf)=!UbZ9hd*MAbwj6k{mLADl~!8XAYRdIPPXM&1V7d~ zdzm*?K&_I=cMG5$$e}6m^pHrx5FfyJ??njoyBZ~X16I1w5=q7WsZ>Y+)7z|Ycv_eIb)P-$L9Y%`4h>h*~ zsy456!)nF(FxchgoXo*6{CpX?pPqL!D{$!vmhuNR36Kzy$eJH{$4VzfjWRJEt9+bxh;8!YKFxh2~k$Zv2SkUXklQp;>DmjN?dnxu724Q#TBiyjHnCx*wZ;|Z5{17=Zw9X~Ds}(6y zW;VvWv~yyFpTvr@7UzuFyYRV<>C&DBrc}~@N5srFtr}k`x6@2!Kt#q2Ig-N;B3r~| zkXtfP)P|LWWZU9GXsPXXS!V~V*aE&lQ;q)XjwnEv@#KL|g1{n=20j}@s=--93As`B z6jpw%W7m#>M)2o|m#w@5;tP|Jd$1`EG@3Wl=yoriEo}!NY>6$-m;9V3*&?;9g0iDY zto0 zPEXwE(MeqsDW)gquB+ZlP$~?2RXd4E+ke@~;9L0Z{Gl*VM$|?^k(q$Z70#xLJr=R&$ft4a?p zY=-HA6kpehVwQ58YJRLyv55%H8XGj)w_w|V1h8Q_qbpy@ZuqQfqf5?`+06D(6fcp&_KY>>cuOnf-70G`PrlvBClH_+ z?KNgThyu#tAi}~`S+mBGzNb{LVYHlVmD}aTiow&tpK4dcJd&9m{9J!af?c}*CCs?& zwaEao?S_kUfv1!mLUY@|x>YZ8I|v%kQEtURu5o~0t5E5l!dOI}Ikblz$i^E`q89*h zXzP~~*hGo)5=sGwLX6K0@$6qa6F*$(lCg=+3!A36F6KI4{`tUk2tn1bMM;15Y*Xw% zXXjn!FN%hABClyBIy$fq=krWTtr$jndDMJdy)q&k30C8x)~`4D=%(kUF{}DHJxyG_ z+I7xj7}}C#gMf8oT>L4im5YaDM;hRPF(Pvy*iNFQ?ncSPSJx(D*#4@ar3#1&| zO3aZlMNS%JoYJv4i#uZ}sRmiOd|!1jM1OUh^w<0(M_lS#J?hviczfbrxTYA&ueZ1X z<6%8&C$u(pkB(lT^oSlhaPGj=3dw$MT}oq?4b)^1Nc+6`hjvm*f_H&!Qu0ui>yt^YqI(`C zC>qX@s@tkyU61FXKwD3p23f$qv0xb&mqoo1#lp zvo=grAif|O6e@r(VWq7D!_z};T0vS+W-2v|Pr`X)4-r;n}JIH8J9t2?K zM5z*pfN;cbz7?5c1;wtO=!r1OgJM>8@3rGm6)ok*%%jr}pK8n!x+XLvI(^DQxB#4w` zGr@w&$FG=dcI73{AM-B&8!(gBpO;pGp3KcwUN-V@2oaC@cELD#S*!og7lY3)cPWPw zgM<;SMzILHg1sRF`VT?=&0&q42KcZ_X%Khjg!6nWI@0=JVlmoa73uZPg-KoRbE%Nf zx|TsBhui~^{eCE{_k$7SKkSGYO1Ec7)g`ivyAo12r5zE7kDO(TaiTDVnBp*vzz_I7ya z$pg}>Hk;8OH^e`u@G{Etx#NjA<{za&a+>8gx4L;r8T*hQ@4QU%dCUK*EpXslTl9+d zea+;2aisC0$gPz*3087LXoWEsQhVv`{(vC8oUOVX_r@M7oL5oXS7^nIyNwZE7N}l) zFqRN!uy6y0&o|)*>cev%TH`q_HB~tQUw304U`r2snPR<}yFvmO*Y&_qQp6^KB`L;f zgLW+})(ps`Xu85uc;^#0)fbTJOXwq|vVp}J>s0L1chaLe2>j`1t!5>!bb+CI#WCQL zy0h`hZXcW5lxm_=)fFv|cCM+jGazZApb(5tsMaw~0@0BG1%T*C0Fg!<&+q@AU|?{T zV0$@vc;q37R`Y3D;RN2pB&hLfuY#h^>H`CpX*WSOaXa^ZEO=?1k zT2YB1_IEmFL5xQDOl)I&4o97|Y=3T0(Vb96|) zEjU(v%C5$;2xqq}(klxt>y*Y?%j?J0XSR7<;2{I;LEVIE;r#Mb(r`HBz#tkWL|A*Pwl(S!yOnyWqf5eBo2Lz4oitSJqF2dk)NrC`qRn z9s>wh(2*f-2kTbS6~6{tE~-*pYjjdCuG1SP=exIjVCN38%xPJy$!Gs$7lED9qj(H@ z;LtLhVyQj}umRb{9i!}OAqFZ9U-zGZJzm6b^6z?`m>rDsY+yVkeX!f34_yPtx&RiS z)(EQxIK|jJe+A_2NH39HHT8U`_HI9tY?v8SG8Y^+4u*E5uxr0rL;b$LD|}iS`gY5h z7*V9eEDdp+K!svfzqlcVzD?(Vyig<)Oc@Q>7n0gTeSI?6^}qCyeSp6;lWq@ry}}ih zOJ(W(JJfz?06~ASV1Bq({~`4|M{7LKk5r=oT^jGS^hb-0>V8G~pl;&i>&PvkQa3cX zbeQBcsknT6gJ)WZ#?et;@ZokJolw!y)d z?7&uwV-oObgoG>uTJ5yTJBA+Li1gjakI`X4%-4Xj;S|iIOu5M__ew;}+LsG@7^!+? z=9uO^vwbIcU$ztN>C|?)L`d@-ga7oC@Oz&W>N|NW7&S&}MXPYW??cBYWoEX;M$lxa zd%A%P`!iX?G)KjaSF{uN2=8uht({&TN(m3d;zc8>!v^A{?0S10=XPT12_4hJ*Ys?C zesL0Uspc-@9uB&&3rT2(pjlVsV_#@bc5 zO(1e$iJUpBm5MI;!og`W8+z=O6vyoFT>zo*cJk~Kzr_x=I+7uh*L|B2m9G23mCI9NTYgFu1`0QS)6NS^NL8~ zSff+l6!7&?9nRWxrU~1l0#4k6u!5%Up;DFbPZ3P4mdP_BC42m<&G*~8HnCyDoDZSi zaj``GCQF9y`Rxkah!EncDydN+j3|yY7%R-t?fL%}2#SEh z1j(Q6jC~Dw(WH^00&2(d0a`~kZc&m*doW`kBw}l2e66mxLAXMIBO@BNo2&o@O3!i2}dvby@h_<*d>^L z-oT;P1K9LP3a(Nv2RAr7k6W}YhRzOkEWIiL0;>Qc>Nv-zzojqbJ>kRQ{AJO zx>SOOHkfC_nLL}1So7NWLn8TU7s2gGTY&`bs(M1GO9t5)mj~pxK7SCqMxG(gHP+*cte6Wj0HzlmFAj z3aX=L3HuhDu4rzhm2n!DZ{&}Cz~yA*hXMd(IR9cWL!=XzB@tIoMfM1Uo~ju9I}@l} z^I$)6FgYw~{NoJ;$$|+hX_WExP7m(9jhO+3?!f!*8`!x1jQwD%KJ){^c?qI^_1ysm zaQ20o_wO4Mr8pYy3$uf*SUdMNEvwT>FT9ooA7A=q#5v1FQ0VMv1m$#Tm5)cn^PMDC zG>G5Cg!0h`;MhDm965~lGsmnt9_*#>K`Vc8ef@CQ* zVQBPlJiR}BLy`Q>bC(AE4G*xS+D>3;xQ7ModDV}5KU*^>M(?ix5#f|GmbkkI+Jrw# zi`fai>j@j{pAs(H17wR}|ALAR2jtORn#)9_Z}SG@S#UOatZ`X-@LyN}TrPqRX!X>5 zEjdw00WT_AZLu7A6-O8ag}9x8gVVEZ7*uurGZTsqtP5Mn=3yE>W-tw^4osZvdWu@) z=fDS`RpkSU{GE1h8)Z&Dvg7V_tjRie zb(!8l_qcVVnX$=Y8)iFTCm0wjuY&c83iJa)LXTI0Kq7B$ZKb|0rl#_e%Wp2Cg`}zh zfFzXp53-ATM>C3&U0H7H;OsxpK=LQtBgcd0M|2;LeLp7D)AcRMqlavykC^usB>>V z1+|PE&u0Kvx8&BaC8L?-k}Hs}JLcrFU`~TZ<+@?X1oMdV5b+fcPkA=qoXtf$AgZwu z6;2jXV-zqnvs;^1jf`%L;KhSwXPr7yPSH}*B_d^lmhBwj+F6#}20o3$GV^tQ@{hvm zdOifea0tgRoVO~(4e&*)8q~y}h~`<2Z1{IXCwhb4Y`DAfyL@(S?VtVEA+RZLkxiXC znzA|=kx_epM3oH#oVGh;%cg~K7uLN>WZO=HU^ZNwoEe^P7R7OipPx#k*hRDNW% zwL2PDsBD_BwX_Y}%11ZTr`OVCe{J4SeA@?3HmF$e5}c zPhu1*$jx)`6SvQ(2#jxNL%-z`ysK_UuSgFv>qPlvHGug^cbvUy{;!KkP)eI|IBkRT z4xvh!fU*qFsI#smcQG`wkHcr%3*fsc<;qMYC|u6652w;~e4!C`xJWU>{TQ#BSp}h> zh(c9>nIbObmo@Wmz@u^)cG3_%7!Wng&QD#TI{$*7ML|i5NkzAl@6ZzFy?mfxp~GqI zYrnFbxlL?G%K0@D;1T8xc5bnbA**WRkbt(+iTAwJyP}Bxfmk;oOF={Q6s1ZdRP|rQ zjxnT=)NOekP&E+1R=e!0B-$Z3}DzFCeSp(!dEAop|Dpk8bTKfjH^B?Gzd z3|GCs_ZoaN6rvtB1d2|rxjua9#^RA?chfN}9R~|DR(VsyqDE3+rP+eHJ(FS8^5irC zlJV!C=)DX&+TTP@hOJ2uN(KLWuQ(kgY<P%;4QbA9bR5C$`$eDlh&Okv1f9ZBI{kePGv_xvx?O_%M_p$2ytKWXL>%prVHTr zw1>R@f|f^8@NJO)pB2NNir-%$UzrS6{qsXLT3ukVg}3f@PXM!J{BI||6LuL&SVmCs zA-ofR9>K@P zU2Xo4In!^*NM2A)PE{34g2%~h%*?XVuoUOMk+|n-un15VA2 z+1erek}zsc-9r0TblKTv6VmUnhyrE)|5?K$!nbIbPLeJnc4-@09%jrS{RV((p!Z+5CS=sI)-Z}kUO`e- zh97R`ryUL<-|s}#tTQ~DjPAMNH)Xq+1o)&|0S9<3%>R_40u$%gsWOm@11_o!ue|LI zr=$p~{${n8>LHp_;f!>yf#99tG9M@a$t7%jDtju zl0dxb8>o4259l;Be4*X_-CiC7L5Aw}M#w(XFR*TD$cFtWkq;II>Wk; zncZWUYGV@Q@y>C#@q%7ZbKRmK4qA(93XX8kjC;4@CZsNmg|yFS;m{I%!~TBzkqp*a|M!I9yK?=f5TOSm3qVooWHQI# zn=6;`s>PyUwwlGStLaDkBTGcS&;8akS7ww#fcYAZ(i8vyV*~$qLD}Lap zTPgZzOG!}G)}ja-)&t|V7D|k0Q=)jl>u`gTZv*;``^b`SBfJ%p$%&+bngf^wW#6EO zn}MF!&Me6YD?ED)c@ivO=HiYUSeNBR?$y7ztk1Mw_>7r!k(aGzrL3feifeTTqLVV~ z{KDvXm+9r>tl^!8(9)hN*$^3Nhf4^DK!P98?GEfHq_IW#@ZL>tj{k=*g--ARU4I}_|6uK~s`ILEOGfx;8OR_>NjgJ#fClrLRCaYm4*|$P+upRGtz?nBx5>-x#3WkwRARXE> z6!JIe+J-U(1~q&(?ObwZVKjDJ{hBa}(;*QUyyC{aUu30q>FM+oFmr zMzKy@BIbxxyK=7-WZZ>k=eM`O$U92*4602Er6b=seRN(;5YIR%N7oaoqy6_p0XQ-=0+Cj>SOBWL-sL0$|2{jm6QA59%(V8d&!0{%O>|VHs2mz#WNKbm%X1)-H429p-}Il z?%+)e2zPUm+{rjQ#PEZe+E(qMKtM~V*34OAVyPkO>+|bk=Qhei;cTi)7mxu0M`Ls9NgCQ z8#M!bKV1V3${HBhCNB((yw7jbEia)Ym~FsZL&Q!|1eV*KEVn3W>}_s3`p-TuhKesl zZ-ma1kE0dz9o-We)f3By@os)V3|c9Q>c1=Q4$rFsaDS1G4ea5d=5M+E$qsYm&){#V zO5tGnujuTtUXabrVPG(zPqvNP%lxqUm zn*=~~lm=&}_u&{gvU&L9@fqXikFV#Yro2Fpc{{sCArSiiz9nPpIdyO z6L343=fi#gvUQ$|*%g5LFB9)uG?x0l*ts$mds!)eQrcSjID%; z5p`6^qkYd}G?2cJ-vhzotb{N$+1^M9l}Sicsv^D|_c&Qo3UaI<3;2 z*3iF56$i_8?YQ}?7x(TmNgU=TxbQCuj`4_Jik*~$F?G+s0jsn*810TkuJm3uKDHca z(LDPc4DOpVWE4k_>g~&3q-lp+6ZIrS2CXca8R4)n+B6KQ#Ysv`Ec3`y!o}MB#vt_H z;+vx1!dUK%&HTC&P+Owvi+Ansy9FRQUv~+8r9^rI5WQK#cki`{_@=Gfg2@F!fUF+0 zIm~H1OdR&58v|@8JAFj?;6V_m!{1QkLb(j?Y@_k>h%-C-oc+7L>|5YDy*yOuU4SbF zb|wogjBGi3`PAi0$5?;iH{g{p-j{O65l&6AQq2~;Ak2i1dB_gj(F-Hq|4hW=S|->f z{f~_XNi-`}{2-~tN;NI#5p1Fgpws48SO^^Ni4_Px!fl`to$pP@Ev<)DF;wc8`jPqpq~>dsRoh6PbdYA8r#yzrS`ei)zwix!|&7J3afe;rq$!_Z6n- zwcAb6tsP@wGz3XQtK1@qM4NSG7-$!htE$G8(~-KwGJmc`Ij8g8R?i!)GPcwSYlDnK ziM#*%x-~NS8HE~ifd4V02Waf{fpoyy7#Pj&{u~@)&+dWd4fUW7s7WCm(nz{ON8jwj zZD@+ZgoH?kt|CB#Jk68oa8A~Q+2aSD|KcNT`vkA{V&LQ#Y#UQC5DxI?IsO z$`q7u=r=x9Af+8smhBIsPx)}ZpSd#}u<9x3?8H|=gT%Qa>SuapRVS+zYc(+=9%vax z70@Xk!EA0XkJ8_h!FkLWpx_C&0x@mtoG;1a0yR(Q(67;iM7lKO1y%{)(cZfx$t~Px zF?#4q2Ff`cu$tyNOfH!w!#DZw>2tso9zYuZVs&FtTGLg1qO1@Wkc$a>gjT2Xl3#7% z{cX=*Z~LwaeUrZ?1T?zr9=JB{zvtLB#nHLxFsD}fd{?G#6#n`eEhZE}!U^_+JNgZ3 zT*zryz{WSa_w(G*$-tpOK-7vlCmkO>Js@Mzy0oOzs$}e`rh^(tx}DNQ`)At%bsC8_@;)4jL29SW#+>3QbM{w zMUODR5XfZ30(nV`3oe>uNJRzycs3L+U^X=2`3nDOfoO*;;{oFhZE0sNmNL?=OzJNm zzkarlQ;xYOjx&!mj^q%O+=m7# z=_W0zgWxOyP~sLk61`f(WlXQ0B@S~3hrYq=+2m3PrP3=A$pMzG*5IVjB8CW6^kE_+ zp&}$SjbD?_HzP|>S&JHnN_H1)J2!!_1tap}Dn|zgR$7xblS;FSQLwFa)1+VM?P|EbUfNud<1OoscBCUKiM>Q^@N=Nv-7@9_DwNegpg()S%sI z*NSqck}(ZpuB{c0_rs~t^{pmq$_d(+E|-eT>{>)Z2-6Gcr>NLq%NlM>pjQ}6i8GVG8x z82l6bn|t-Ix$h_ewg>?jNW5Tx-rIDM!l|>7hJuERVs!dcLW((I)Q4mI;f{z0W*C8E zZijOxzC)bjlPv_A7CE0%`pcUQbO{lo{ZlDq&Cnn#yN%5=g^JYyLkA^6x z^4;=EluKr7k9|>y?kwmsDdm-v!_d6~mo@x@gokGvr?Uc|iL_4EU`6V6P!orll@X$1 zU1r%B7n9RmwR4(ClLg>F;2`86J#g+@KkRt>EV7@`#Nq{cf)>c)4@(lgkrHGIkXHY8 zM;87QpxZ6s-lWw5)zSUOhZ;IG+&PWhLi%{K{Gs_Y;n(U~To!3TgPy@}IR?!)cQ`Xa z6YGE-P;_^f7_VyCO1 z2~8HW{pUl4{jDjVzl2FZ zrUf7BB2OB};GlsSczoHob{cuR2X`24tMwO5sEMJJVtH==Gf?<8CYNk&xPYkX*8fci z=~eMnSV zLH>gb!a)SnA43(?HWQBkhZs;Mg1ZB*>fafN2eq_;stZA5oqbQ%YwNUDb#j*`>5|nt z^unqJY5hLduA=QiiaBd<Zt}bxvdkPnbd}sqEqYVElYE>u0Wq6wPLpMvGf4Dwf3TW*29<%kB*e~UI)a^ z;`Xc@KIw9M({0s`-%r@6QKwkgm|LzvZdwnpZd1?5?$2%=Y3Zl*W5nyl+sDY-3ftP- zL-9#c=Xd7!*gM!~-96pI-Gd)0KBPUAJZL&#u1qNzU3xZW2Q@usy;^>a z-YUE?jxxeE%D0fXxVZFq)P={Am|&LB-CTIi1FN;@`eOYJ6OS3}^kdG8=j!-%;0DvvovNe=vytP5+n&j2$ zmG>(f$8fKnuc@ywe25*wY-)lXZ8j!r9K^8zdu-;cu){=~J8ihcF+&?yZ4jeFCp&^` zxP?(sG*kEe7bMS)c^&VM2IdqYN0_*sAJ~G({O9$2Yt<_e7r*K?uedUrY_<5ZiO0zT zsB!L5BdnWP*aX~>f$dTzv&aSpCJgQhi{;x2`&_}iMV~m4A9jLIo!Aq*!MVS z=7%h77Eo1e1?6@}UwmpMZC->zWW17jl{y^I*sqBe#D%Th)oAM-mY^;W=vcUcV{9*~ zs>{Ld;XmRdsF5WF##m!NiP0#iw0*k~srakB1Gv*l%s!DUX~7@a5*URslz& zA%w58IDtLqD~4hg#4^Z#b{#<(jvgoYA=*A{Dn9tSDf(D`!+4-?wxDh|0?}eUl-R8%H;BQ8e169v{%#u8)bv$4+F9 z#uii~1u1k4L}`h){VPek@>>i5<5vBcUH=XVG#B-QC+VF2g8rjr5PUh}6=D_&7$-_HKUqo)k6V zB|&@~^WIhN5S;C+lHP^Z^2nqjNzdmqDoYEiYYoBPGzPBSIsLlZ4#A-Tqu~UKz7_Um zneA%869oK%@DGQ5@4C-zU~u>x+krW5CNt1SfxcxgLdRclpeV>U4Ep&kxRyLI1g<^| zA$Y(D^0@PUe;`VZN+jC|?xTMBM8`NOfW!s+al8A$rOK&TQ&wIuC@(nb8MH4vwLPN` z{BW`LZ<>cMn6AI!D*}cvM_;0!C2PEjZmVq%Ap@^j606jrwMWN?FxN`F)#NIg^>Urn zsx3r*o%?M&JlPyM^RbU_-^mB0hzta7J^i&ga!UngQGvx?0Z_{`U)N?;RVA@jR4XdV zSaGdv(W6@l4zIeIW${+?*RDd>J_7=+LAFSZgY zO^Da&pWs^9KnpK{cF+;=;w%Ww;!6N*vyV7bXNMt0kofq(?F%Fog2eC6fY7zfHTN+@ z0g!7}%CLt5`}y>@AiUuWJ~A&IGgjSQ`IWVd)uQ?HC$fr{ZI2*kCy$eRDnQnlA3<=h zfu5uA=NR>OKzbVN++YbwSQrhQk&WEJrxF49K-~8OZ{2@$0!P3whGqF+;gS(MaEO^{ z0|bwJoay1&@qi)!LPFy$V>f8vAZFzLC(X;|hkjd5)B1k6qT#bojOI)cX*Lp@yOJxn z7uDSSK~#ECYpSZaQCCQ%F}?bLPM@&V@wgWv5eCsC|i5;1Wf zpn|4jA?# z;em&tf$Q@#rb^6Sbo2ad;epOgOVKm2*uo-3h$tZf@Ca+|SPWw}*wZzE|;OO$hGjU&o;^AAlg zZRucCnyEJGojx^yX@JXo&XBqdiP8cBBK|1L%$sKT2ZYZEppUqi{ibkz2;Jd1#XB>- zgsvn2A;c@~ARdTr5|oF??MQYKWzDDuhIv5UcPIjp_kdEt)OSSkxEwGO;qDCVl)GX@ zAJc483Ffd@Rpxu7Jm^W}P;H@m|MmF|*d0*mqi*vfQD-YzR%WDNi|r&wV(wE4N-xL79zA%o%%JIbmo!lPg=4v!u)LD&FFhNGt1N0 z?l^+Od9ze0_GV_Z8HdqH!F1T%woeV14}|otE^oT*9d@`Jbl%H2zFv)eT0$KehX+I} zi7*5vi7b90LxPqwoj5RSoA*d_iixZ3TXij#@qBc~jKB_|YeTN^nljSU8K|DMy~#?{^Q zj|t-Z`>O%k>MYxT;yVlI4MYzM3sfNHzRJIm>R0PWTOex1Qouf-K@GKI2Oo6>TDrMc zA4i6e3x;UsaY~7oAT(Vr3;UCOstT3DqbaY&NbEkIR^jfxcRm*EQtXnoanmlx%OkdA%h!xz? z0Q(Dw2%#qZ>{;|Fe)#esSQeEnOm^KVV(u7eD;G%xXC-sUFBG^in0$haU1LZG$k2_N zjBiFLRib7>-*s%sM>8c9x_%28!aN<|O&B$eucg4t5N-Ugcq6ZWB7WNc#=u#VBi{{203$g!1*Bv4MqJL_xhm2Q_1JSZ+qILcbIedL8I` z!GEMn*Ugq*nw1ulvR=VW(QRXY9;zV7pD@mDcC-AlP@R?aDOxRaIl$!Y+%qXCHLR>3xh4% zwK)C2E6I;qjR?}pYlIYB_?{lIu#dDo13UW@>B_j`3KO+KbyQ~Gf4XwODSTE9rRD}!5R7aUI zP@CXUa7!K_Lv1daU+#ukyR2ODN~;1X*h{{+I5ug*R1#SW3p+C_3-%QN$JQHs!)0cd) zcdiEyAR+TiVRd6=etuv+y68fC zv=-u+LyVF1=tBC3t{0cXEs$j?rOL<3%8Je&&)&x^$5~eq7&H*78+C(&wy78KUT;)Y z1|iX0rF14Wr%A?Nr9G&JCⅆ{eWx7-ukOmGw`uxn|!G(ob%YMe^M2 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 literal 0 HcmV?d00001 diff --git a/src/modules/oldLibrary/Material/references/P_Angell_et_al.pdf b/src/modules/oldLibrary/Material/references/P_Angell_et_al.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c6b0f8b72fd19afd8dd4cf8a4f2a2d5cd5137431 GIT binary patch literal 681273 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

@j+^hWd=CUIK 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

3#Wa{pJDl(x42}6nua0fpvm5*70+f_O@9sQy*?= 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

>W5B~) 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�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%0Dc#hZs^oQe5C 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μD7z_<+fJrQ%VHva@faUPK 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 qPVMH|bI=_cSvvw9#p0;{O1O#D^dN literal 0 HcmV?d00001 diff --git a/src/modules/oldLibrary/Material/references/Ramires_et_al_1995.pdf b/src/modules/oldLibrary/Material/references/Ramires_et_al_1995.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bb76a9c9eef536835cfa7455650b3eb84c45ae39 GIT binary patch literal 578010 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�SPYfjy>xO5I;STri@p7B<92 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

}EMcBK1io5$*WHl5J$DXH2Y++?8t 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

XcU_9S^0vLr_U%~h<3@dpuE`#Pq= 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≥Zlx{kZ(c1eWoz7dZr- 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

F;rfy zQX)A!teQMfH3}EyLYzCUBXQb3l3b4Q@-h^?Ue4k?E>H~QhWssDfe@E0$_>3+V&J$@)V69HRtfQ)|7voMvwYT z_Q=`M^YJuXuh;~338~PZ!A3KyeGBF4?$j)nAuGgkot9;5P02&*$8fHC|x~@=mI}{|G2# zO8|!`nE?7GXx3G=_VYoRiW!>QFIy4kLG))j8LHSL6Bc_$Pn*_sHBv01h0!LpP+~*H zf|}FGT;eR%D6PN8405KrAs$({bajJbQE{`#J3d|oC92Mx`1g4bTQTT??)j^kQYmN{ z>{1Dg#(Mn{EfZhUe5Bt%xR?svQJgey=55PLF$h^a#e3HXCRfMfS>`zpmCaT zWu)-5u6%mu1`r*0qg*|m4;l*zpSP8^Y_e$6B^OW)q&=$BbHaw0aXS(IIDb4uL_{HK$|ljEL>s6mtUNUKf*3UxQ3oh9yfo|zCTFZzR|CfZjOI< zNnqO+y)dx-QT}pm?{(7{Xcbipku`6NVnluTg{2MjoceWv*nYV3L20_^BUAM%?`~k}>3=izlNc=l%TPu&V4SBIyN`PGq>hq~2t>4Wj7UIOYcX1opxL8h zc&|oV3}|fQf)+DC*2L+$h(jsGyK)4$e7Gn4E?ksTjBqI7=8+OK%n?=}1*N$NyOE=3 zc!{+*vW&c1F#Q;9YO~GP8XUX?f$8wRQUSaJ|_0`Up;?z67=B7!v!+ z>4uTuKKqQBCU~9X=2lppytu;C49I&f>Ekr9H8$6>F2ad z;HB1CYpg(<2I+jPEpBLLF&oo;|%(LOjt343y-19=`>bor&r z{x>v&N%10Wnu7g$a)U*y@#9nabJgnGg}AFf(;0GV%AOwMp*3{20G=f{9E&M^oL@6- zW~|V^&|tFp>x)x@cK=VE%IZ_OGw<*YA29~$SIPryx9he!JgIbgc~&*+=lk*uEXIVe zMg#lF$fW6dk=eNZm0myP{9MciB%spjlbR!|C_7EowSxY3Ni)6qtcmOv2*)l3&0bH# zzl`<$GEh>IwWJ(e<)`*#H6GgaATv!1ZNXEkNF=Z1=b9!;FOxj!B@c#!k2Grv!v8~P zs+k6J-*3D2r3Y_W>-K@xFZTi+&18ri`NLRQMDeXKkGe7wh8rr;>-kTLj+v&qz? zgC9Q>HTru#McCL_{DUaI8ko!)4y4Y`9`id8OyhnXX*_A&;yjAF+6;cQ`h+fGxhD-Z z1h67401eV%vEevPB+K0D;SNNB<{95jNUpWNpPf1ANNWZ5r0ZC}SE~nftWY;^B3GYT zEyUtpzOc^|Qw8uh&LmHVd31=U{RQim?c<@yzV7;5!p?v14O<9@ccg&h9n)|Sk@?Xa zS6*kO&>5;!R$N-Fz;74LT!6X3rYtiduQnnRUZScIWgHfBxB znKzrzGg7kblu(UYH-`@Xlnt+RVg&8^nVTEgLz^ zdcxmv9xJD+=oWg|fvc7Gu{yTR4lsUPn z*8&m|+cE^N z*2{s9%H;F4vMAS{Wo~IfKfPySt0P(QAP53YwV)~%0`ks8!Eo+!ARlshVPc+G7ygkc zFEq7}HdqJ;XD|H&OLu^eWr~x~*4EqGr$|$KEYQ4oah=3`qtB_m0UDnjTl77$25%-Z zD7`{ucsARIP}CIT5?opVIXxyQi@+x?%kkrG@R9ufq%P z3@<;zD8GMHPBpmq;e0_U@t($Pnxa;2xgljGDrt>N zqamXpnr)huTdw17iZ!^5jxu5kHBDoZVwjTE%!Ig2gW5pwz0U6AzK{EQa6S4zxOz|> z9v+G%a-N^h`~7;AI=;=V8+%aTlItV@3tqXs^LOUu>D^2}M^3Nz_r1h^n}Ew1%p<~p zLiYeXzia*-&b$I8h)3$)jsTaHol*Dt33+)>pO+crTl^IaJVy}$0Eb>+hep(mB`I3> z#qWF}1T1hcZ$J~xXH~?+W*Va3d81MRQUV}u-7A`5(^@L!NW{+}2T$lR!Tb^x8 zx=b{Kd1khwy7HZH&~s9*lfjK0Irus2e5UlqjVrNH_li>!Tod+1kL)uLYbQZJr}bU9 z-~Us|%h{ar8*<(kLC=SW(=G4NsvMqDG2gM;(POoGy$lkq&qC1)B57s*9_NkbyWR>+ z%pXWM?$rI!9d<(F(@utB^3He^P_)D&AKcklfjWQhJEU&_DiN*Wz8{4Jh%h>9%sH57 z^>n*)UG$tu9Q&vqz&2>$j`DXte0H(yfn9NE`&@X?k64qxDBn%}U?XtNf7Td;)BTKz ze`$KslU?lj6ghvH|K}-ZTs@davrTp8(7nuq+cspjlV?V?M9k5*orp7M*aL4_C3^xehTI1d!wO-$2gdM8}J&)+He%NQlN zOS@@_k(*sG#}N#4H|ewfc|Po2F=6tcI2Q#hPl*AV$DB119KG$mNr;iH@$Cn?L8P}} zJBIDM)$92Xq2$vA4G=ESEl1VyVP|j&S3U^NKHQHXv~{l?`U>2(3G8eDtc4poQf_$w zPW#spt)Rs~4R``O@7-7y68p9?130>xQ3sqnkGX-|x&_>i<)X*O)DTp+j66rcizhpG z%5!8Rcp)|m9)acdf~^VaJsgAsZf>-2%xymOTLu{Gt;9aHc4+JHG*S(fhpj%vdCRZvrM$=d#>*U&qbi);s&% z8{F3}M{#3@!Zi&R3_=f%^>J0h(-sPs1}yON8h%%bN8KvX(Qx-RVKu4(6Xq{h{< zbWF7CYU#VSJCYWxyn8#<#&C}`cIB3iU!T`RyAhTEv<;Lltm8_6QRo`p-(l-zkDzXT zkM}<$H~8LewixcR~~?~eo4sq*4Xsl@xo;T6y6NW=%bMrPwmRUV)m0Y49BuDHZcRyR&!`z%sQ zE*Njsw_3zxof{sq;;AghD2zo#=rHiPudc2Rc`WKoms zdDJT?E!xVGRE?^coOa&wglHlqur@0wv6OpI6vUTyzwZ;S)D8~c z%rx{L@K+`c<#%%JCOeh9M(|2Hb3hK!I#W8YZxanDugDZq#wsM#Qa}T?TpsAcPA;NB>7?n86gP>Uc^T{q;g{^gb#C5P87S>>D4)0d$MnUu>} z=HaVpt^5w& zJ=y8Y)4XL;4lgN7M(}|87&N7N8zk3*Ads5{p%uwAy+;Hh$>VFI6rL&yX?A5hmBBJp zD%GOc$+c4PsB&nGtfGt2TJd{2@)Hf9?*f!kVqL@nxy0; zsjr?`6M$Z0!?VPh82Y;U-;ev?OfdA>0>R$PI^68-mE>sYl2-vZQOY8lr{-T=`F)P3 z!~)gO3>Es|CL32l2bk&)`#ApVV%2VC6b1aCk@JGv=q*aM)H1S>2eKYsOL-e(-p_yh#LJk}6r0o?$)3K`|!(dG2 zw>Bi)f1TlorOD~Zc>PGK^;GcP=%}!A7K-A!n9nlNc1&$BS{PfSseA<6 z5A6sKtxBmvVExON3&3nni2DWe%Fzd>i_{IpjF{?=-l-ofr1;7adGP@n!e@couci`i zxkgY+2ZI6y#d?5cP3#Y97Wh6&14v&gOc1{KjkZhY^V|Pr35%KC<{a`$j$5`}sIXp*k{r%4BZPmbnM z2rzvsP0I7s3Y~rEXWRt`Wc|}P41i@bt3kVFqeby84J-?X%|pc%=$a69uz?(1RNUPK zGan>?JshZH@okL2sENROvF{szN-g}F`LqhbYHJ~if3zd^qv0o>1T@T$OJ?=Qco?*iU&WP$L?WQlo)S+e(k8s zwxah5eI}O&YKud{b*(aP*(Ujna#z?Hcg`jqinn#Fi1v$YRI_9s_f`#I0TWX^8 zS`U~}6;SXxd7H`WlygR*PmX2A|N8WZ;Aj4YY+6Gbb>E4Y4vmb%ZBF^#bo;EV9Jlq3 zMrn1PG;F6rJ)ww6SI8pM1BV>eSZb~gJ1)3_4=Q{48(4g-R~*w@FMjuv zZ(!Xo>UHk@gl6s8-#rzi6s$#Z#V;gfvDA=N7d!R4#V{^BU+ojhyUmM|HFO4@)=G^u+!Hhw;W{Dt{FYp!l(-!B)=9Dd}8#cZ#;a`pMXSNrOk z9^&nnZo}3Rnx?&ORJ+>C8j72M0qpn6T50AK+i) zYU&1_>7Tp#X9h|C{T|(4Sl?8iVrS?de#tuXtZMg8FYFT{wkQ!7b_QOI)zfEQ*1dNu zmxLU(&?IfLWqV$|c6Aapf88ly=R3!pV^{;tGyl!8)qhHZs z&5O==&EGqse!1}dw{OQT#UmY4_4Se0(bzYZA%Wt=%Mp~cz(0~P#IZQGuD01&58~#_ z4Pc$SR=*$ERKYER`q##f%oVPYrx-9O&la-vuLCWQuZA5FTtDkKkAPj~=D7TZt?_YD z{J2~ea?BOma$==5FZBSZgGS(xrRI#%|NH_BOVW?{vA7!0uBb@ObtDS8*tg|G`#p7q z-SXTIGaC)Z(~iuRHXEB_mEJ$Ko3k(fLyGULH%V{LqQ1><5jB?+I2S?iD|K5d5q!dS zB=$T_`L+!}V2%>ng6}hH!-ZWR@H%K=Z(g>i;N6b6wm)=y zSa*<@@7x^upeNlcTpl0^&J23jFI@icZ-Z+ZKy05+D*Z)~SnA!0vstFwyL%TjqrH#L z&H>?HR!iM0>$;cLj~c>^Na5k$ot-`{);fXP-qg5o58pt*WVbwu{juNhGio}JS6=Z5 zEET58&}=G5*pCNvLp{B~UgYJgV`EX+6%dc6i!EW80{C#V$GqY$hT**mDICido9*SC)@PQ#nYwlnv zQ?oxz5wn+{wskC?FdiN>bWlFKWTKOo?4)NBghWo{9OS+M zbxKc_HSCTM4FzIqz}-(R4pEn_P0?l;%TQ}x#~TmXdV<5eQRLsMCr_RoCZ{al_lL67 zkEm;sP{rU3&r={%+55g-UW0<9mZE9ZVeJk$y?hH7NGL(Vt00NXvV@>E9k&ri3bcwM z|I7%TjybPZw`mtFmCeigVmZ;|*EB9}d7Lg^ClTU~)hJv2q2CPC{&`;k-@LrDWvZg`POx=E$(J_R&6fDNV{Ojad* zJ~zK;yULpeeaop7>8e7RbYBL2wxKbIhD}XmFh1^`PEkSXycB?cS>gCE!yw+tn@vg) zFC~^ISx0Y_M<*X-+OgC-QAkMmT}$G%O{oH-dpv4l8k$@F@T z*uM{`i{?a&F*Ht#e~w5r?N3vVIY^gPyY}`<$f{KcI9EB#5IoAlLw-w`y&kgxT7%q{ z3;KlWJ1+O;nP4Q|w>l4f33cn3h3dMYPd<|!3e|_6jmgdp3k8{d&}1ufDY8Hz6@jM(`P zSJHW5Yxmp$I>=r=J*nRk_W8)_gDaBs@f;qc1hS#cNIhZ59hFOmC#~PTAFxxRq(6!B9!Rfy`J8)%;A=i)v69pHJ^R} zg?U%n9rW`P#{5izDGTZ@Tj8r@l-=XpVNnNvdL|1ZXKhhM&ScK_Wr)skk}c-aCDWgZ z4w#!9TB%~Jck?AMtbsFLAR&<41&Yf;{Y1~dva4{jAGOr`GQXTV>ty(ct zjV8%N`1UZsRG~i5esWIWYtF#N={pjinL0gTH(igd-(!`JU`f-AV!A8G#3WirYd+VY zy)gOMmga`?xMISfuM6lv3b|mp?6T7>0T^@cqV^&tz8NI#F=HZW=_EYrysyi_9~#9; z!F(;6b&y)%5B7!lAiNQ_@G8z2HHQKM8OK8Evs)%x^>1f@RV6kwA4vN4^pM<@TRPTIK365Legb#MTiUHIH5PZu?!1#}~9IGa)jv^OBmKgQIU002&K&}jDQCgFF? zr3*Dt)cg>W8EL+TQ2;A70Jl{iZ*to8*e)XsU~wNuw7|3|_+7Z&HfOh^clU#I6B6w- zW)<<_;pG!+R;Z#veqg&!l+xXT<(*2|NCfsna7EKKIm6N+#65RCcJjZvg8{VA-)^ZX=M!gGX@qlp}adm+vFH0$53%7E(>00q%z>m&j&BVsYsBBM1MI@g}Oh z#hugl?qGh`={)A^Q2(yo$kHeE%+||&1tKr~aRYKN-<(=sPtcg>Z#Ar=dD-$|2KXvX zoRO`2;AK!U;9nuy!yle*bSXsa!bx6vGm6oM?=c6*q8^{nd$4it(a{m7{(IqjsKrMu zOG0*vM@h~PO6{LlxNNbxJP^?LQE<*q9&aOzJe-)T^Dyu1$$Dh2SB-N-$ZxQ~GsIJt z?9A4-JMZpK1wS9$Z5vk+{pvWj{-7eWx$tE6CRfx>8(sXb=j-#`ZM3bF=Y z3v7t&UvtB(u)Et`U9(UL`^!o`i8ni)h^@8`lSNksr5(&L7l_`kvZeVY0S;ZgPz()< zp?}&Lw&s>3gJQxn$w6dgC!~tmxfh}5IC#4UtRy)KvV!xce-N(mZq>(J80yRe^Trn~ zH{nGr%&!{84v87sx_?Eb4Kc`MPN+cA_VQ+K@x9z1+OT=Z=f}TkfDgRfTL*Rqz#4gL zGt29m({}V8t&-Na!abW_Y7*?V_(bo6jq`ia`>4OQ*$R9%wU~bwTy){sUBQoxRgo(4 z@l~#%1Dla{>!Z_d?}+04a#Va<10&8_AQM5wL&_YD5 zb}q6}->N()0Cnc1hEN0f94Kh=;qDfIbK-omb}at;RwvKnVKf#oZ|QnNvCENV9NSBO zt%U&hZ8594V7>|W_QT`TUONSO#v7h}8&C|$IJY#tOiDg^J~_@x!daW)wmBXu1pgEl zg9*2c^LCHLC)~P=J3R*K2<+!Zo&W~(qTbgS9J*2d2|)h|5*3waHi2|vK4Ru`kMO0d zV6M3yAX?1Y>NC(+5S4K7WP?Y9jB&wkXap}z=O?fppr0}XW2u$qzfdayFi6Ks40qQ| z@GK-eD*;iAJ#e_ONP}+_Q1@K-0)gd7s7Io*!Kn@Im|Fw;FF3brjGz+MP<(BzuN`83 zQZv(bqZ@S%pgVE)$GsJoPwC8+ggX^~CdT7}M=jyF{aJ7~lGyq+a_Z@+nav3`$B7fV zhZAaGm6l~f?ub^@IQ)P+VzQy(gv(; z>YqN+(0;??V5|9!{&F2bDSVs!$n2NA69^puoYdRw*F6$eN{78R{&;<^u{w72?YuN{ z;fluFLbtRk|7lK>TrFWRR%2%(1Nqrh%nV+YIL9)pO&jO{&5y7}eEZ@((~G16ma%PA zR_a=5YM>dj5g1Bg<23%j;vPRbo9FGHHdlf(HWTGO&pf#&E#bfc6q zvA$^SA0N;tU%0ZZu?L!SBk^G$9q*cO#7Mi&PH4@CJ0LnTmZp*^)7$6skBgv1j~(Qb z@)-wJ3>0&%Tm&SZ5-3gigl?$cx0tOw$?Xp;$Yk}6%9(VxUvN!YD^r&UNESBM@uq`%XuWERHuywupf+jpD1 z|DprU4@rg~{vylg1_Wh!Ek0#QlRy(Suv2!aOkb_C*S(Qc61}9wnK)|j9GZ%Mdv%|A z?K@rXR0AsMw_mGVshRIJ+_dQ>jw4ud3x=loU%QdeOS=WUA;@zKuvK;-Ye=3t zf7A~?KPb0fVP(hwXvMV83nFK)=JO#hh1zgnWq`oQXiXg5vP_xNCCii`7HhfKviQgD$%l>d)ZO08GZ($X`*9d>d|$a7nMsCUcf&oz?YhKLLn#va zCWrwsrpIEpahBE4IH=b^v4a_3T!hn{78&p&sqe)~)Wf&W4b=5`)`H!MNI}TbA|##S zD6>AN_(MDn`Cpy+AEz66kcvFl`=SF5IgPmtuIf|`{>thaDuWy2M9K5 zR|@$vV%Ir*=)sPzRcW??l%D?YOGdo=gYC3~P~5*;IBR@H`qzdo-2sB;`BBqi-kMi9 zIcIU{CvUS}0X=N^@{NC56y(2x*4?8s21`LxX}itA!+v7AhgIK zs~EEbO)AdP@E|0iW~(|o)_T+?u@KPpWC5bc47WoWV;?n>*4OpVf%YB_y&JSz)kvoFB0rngoR zG{TwjilK8kvFgQ?@HZ&B%Md;C2>5tBrB+9VQj(M&m6bHenEC5hr9TJ!uPrSeB$y_R zZkposEc~p5>7_v@8>WxgUvKL;dVaI`;SO5zyQL>{?);&(k?r1i$mEaJn^Cnp^5;`@Q2Qrk9g(Z$8czrTN~<(o)nfr9!Q)&GCGR|Jkm6dvdbfjmkJ>oY{?O!=BeO8exj;u2T6foOIvkW&3&G1_ zVr_fNgl}eylO7C=wD40vlhI0nJszhxmRkn|2UtzNO2(Hm{iW?`6A}LB`5`k`0?V%i z9We=czoXP~g=hvX-iv5BXna=h+koLGt?l_VPu&R8$3+|LT z2Rr;rWflc*6g^r?bVbztItX$hUkjCJlIvNZarJ$okzNSl{;dbbbd+POlf?!k@VkOE zh|`i$0PfIOTw#~LFL?izObxI}*;UE@q?ud~YFtMFKA(R#!K{ z$BSsck&UA4o0>U%+NcP;L-*Alme-vNo^QUdEbPPN-`6!ho!6p_Vd8#_Jm9 zLHDYz`cHN`M1fYrA6X|R+S*2RU9ZBg)aU=YVHc`q;#Q~#>Jf!1zx<}xVA{OkPtMGF1t~(ZpsW1{aU%;QG z;+mwU`DP!UW@XK{{X12YVf)PM*|)Z@ZS|l3Q(=7TuX25q)2{9FD7GgPeuc1wAn+)F zU(L*D1)-?~8$$6n$2Eiq7D4B?jbG83Nc4V8fK}SHLLZjfCakFVV>~-qpr0DY#6G$D z3ahh^;vC%gTizBN{M8-{P2H^zj=F726$p3!^Q5}zq2k0bW4~MdE&Q8Yf89VI0!GmK z)Aira{QS!HFudpqEbUOj7`F9zeQBYWqxa5?L%FG*FS^0=4ADZ^s4=p+nMs170g65A z?CJJW%8cP%0~m_G6&^`t35CJnIA5t*56FbyRDz~3$*B&nG2+M!utHrbsEZH223D?Z zBXMJ62_{=n&n%4p(LkaR)x^I}6Su>2EB(qtl0l@(`D97N*a%D)@eqA^#M<(M_00$S zx|!G!z-2iT_hBVJVap+=HHH~tL|h$$Az0fZS!0g*?OEogLKlUY13G^D6y<= zZeO{4_Q?1c;kCvCG`8fsmFjk>gZizEjp${vz0-+e>E`(8fyh7|K}EQBL&Vx^9k&?F zbnhK8Np4an7WZz0jW(L<0i|*-pYSjGQy4hGFD6A}W(O=$0$+^J=%a?)CJLUVCW+3x3Nf2V3mS#8%M)*j_c)M|W-O^m+#Pmxq zE;<0cB(Ol;C%`@&7%d_(Ei8!FM`ZEQZ0}$F_WtxKJgvI;uHdD`RJw zuK2gmfkGcrNJL&F3BqGdrfNyzyvgj!uh*$14A0azA)R0WsI(4xY%N_n(vp7BYCVdZ z`?fLqb9?~v3hpeugmTfbQs<5d-D(!@-l2(3+lIV?u=f7~!rXK#v0*xE21p|9R~P@z zdg7a7G^G>`w%T)RgzbsI;NB8DwC%{`s<4S`zbKb+IOIm@@tm@t#bt8P8wbik)fQpw zG)dIyAx-aBgbofs%QLDpnS=hSCdH8|hH7Suuo>d4%k8ZP&1zNaAw$P@ zpkk~$?hON zg~fpRuk^KHH6&s{&{z<-B1l$1(h96+ z7*Jh|ije+?2rz@)^$vv@`3rd~5@owAr)Rb;L!vH=zaq$V zqwjbl)`pW(>cq{_aVis^`rghz^8XDRgDb0!!^Jr5vK*|qY?@Urng47lk z9NoJXhf-#;{AdiBVm3QPxq890sSo1I2e}Ic(t_C@iJ0@rM<$l3%P1NAxvsL+te%?L zKCQtH+8~u7;&pNsyXJXfm1wPoCmVtQVpImopv}N$owUwb{9&UaMAn%iQx8ME93{n$ zBk#pV6MLg0s55&f8vCTlj$zviA02_qax-=p6iY72}A}vv1uzz9;4byS% zZnROLzAO8o`>92X&)nI;)xs>5#N?6Ueq=H&&#$@iA%4;%DgfZhr<+JHu^&kG1Ad`n z755Q%p~dUFRJL{pfZh6}QFvoj04*}LlCmi%-Xb{jn87HanIE{b`2AQjiqLOEgaaO02~20iW5C;07tMX42|e?8DN3%A_6Z= z{9xBy8E+AryV>u4__VMAac z$3}w=67rUHBFo#$J;#3YH=v*Fq77$<#^pAIer2#%zi_(+K2h0u5Hh}+T1jp5Y6mWv zsi?06Y2XD#r82RbweowWaYVn)$aL0Ik4bUKNj@d9zA2+pvD^-5JJsz-+e8$Fs0#~> zs|aKws?MR9R=3S?;2iISzj_nJW(S?l)&KH-i&JiW!inARSKzB00ha@!&~;AFaYV}+ zq!~<%u5gi7V6?66to=u7Ks_I?@5pq;AOAt$Dt^wj+qWQ z%lT(0xbf-cZ&`4#C`jmP_5Lm7u)(gn6U84Rd`c3YYV1oez^ZXOH!Bsxq|1hqFO2y+ zJuz%UxEsTuZqCUKju#_7bBzey#cq6(%l$jwuT|#@bY5O%U=E(UE!fhxo9!9!Tei`M z&A+w#r2lv)(rG3PWBrZq&eBRDz=}Wq@a&&>J=>Dv=T(Rg(}%*b2G2^S%tCP_)6NGi ztf#>Rtl`tao}?pdHZ}o*3yA8v=eM}XCSxzV%NBg((|y&&&OcWC?Q7H6KjLfCmLDX} zYtQ@cb+LbdpgZ~={37wE+;k0oGdj4gJcKk`#!>V{>xBl`&Udsc1_#5Qmlkcy7zNGX zuZ`dCX&QU9cN?uQ)AAJF9Cvj;e!FSI5b}VrPWG&+WR&m^fmz@lfl0}Hb*iN2`XcRU zG3KMIt9wKyuDy24yxl#nWn|8wd*51KYdBMIsY?&GRmvV707Z+g4DbFRj%f%(r5;cW zcR=m)AP`CxK_Kk}Lb&mf7-s2tV+(L<;c(gkRE+#nTaG6?RCk+kpe-!OgoUlRF9@A{ zI^1Bg$<_NR>h!+K3Z`}N*~dvvwH{{)>6WK!FXNN0|FBb6!zrYwlwt1YTie0;_hyj$ zA6-X+j{mKR+k2+@cqPln=#Y&MGS9~T_l6N5(2UVXd0&hvb3q5Ztz&A8QR0}~-`N*D zQ$t?pRv5uiak-^Ma6Iw(ejNOQC1K8Kn}%uK8C|}&r=W5pj-qMIhnuj7AHL|C9*(eX zTPX=)7oQE&pTCxT^>Cq8V*HQCj9#@F!&hydE#15IgEtV4eu}kaGtJK%*9xZcz2Rnl zEDa~mms^O~%Sej$ORYa%n|kki`rP@CJQy30J2i|~DDcdYdL(u$IsmiMR-Z&_L9_t5 z8Fwrpg5(CCX>-nwQ~KBh0A2zJ0789BISMo4?By8$i)R4l8ST63A`3x&N&Ov#IqNx81HW|rna}?Ci=UruLR9Tvc`87i*#vjOV_)t3!5WO^ zVQ1oU^Wt*ro`UWoXb`Z#4@nC%l;bd>8I{0d*PuhZJRED#G%nz+Q+pcr+GIBT`++dm z8dk?;_ces6zz|;;V4(YW1|P-8-SF~W8UT!0(2NB1gOzd;EFU~xz8NzJ5T~>c8U;;` zCB(uV1FY*3QC!b_ZPZD4HKJKl7kRO}Vr8mzPf&otSVHMK5sd9w3d+&FR3J%(DJ*Xt z^6;*2h(X@^h^0+@tlfKrIO=`>3p?hejdq{kir|ffpBTQ^upRE|3P=H-A2DKW>wG|I zX=feQ4!#(2Xi=}=NZ}jzG@&riToWB66}J$c^oP83rRJv~#=#17JN~8VOS^`Pcl6BJ zh9S9=dQ_OSnS1Df-ZRfnd($paii-rxQkT4gc7B_WtfZkSCFgm5OJLK>TDS~%jkng= zRyP&z|G@3sn_$9NINR&Gye|!%JyGE6>Ubnid$N?O&P%JxuVW_EPsN|Lyrx&saFK6$ zjo%RQa+iDpFKlq7WJUS9CEVC;s{6jgs>F1#g$u3#8e;3~!EbNoyfo$3j9HEA2-E9o zYG&$aQLwfi82~ z&1z(}D&ERba2P~@21em^H2+2(yK0B4lA*#tDfy%Do%FV zYCGkmJFo7vcsJqRgcz4IvF4;+bso%=dC8&*oMp$?#9PZl8`ZakqdD;UX?+f_$3F-$ zm@Tyu5rBldQ9YEtU`;q@3UVZ0GW zg3!=jQZJcRv()@8kplps5T_uC{D?ZGDcRt@5E-5W`Q_|oK+n5bobkWCr`V~m=?=L(h)D$G)WkFqcrf;Z}9SR9& zSiu3gp~>YKIz!DQU+Xm)693yRQ<#KxGHxgu5030>y^@@v zWtjp(k;(Ey&d{P%;r+^E9$X5dK0FLpWxvEwIHGnz$QMgBAULjOspkJ)mWA9Nv(h7&HR*!Bq%GICE{7^TshJQB}IbKejfzzm1cmT2!^S<4=_F@x;j8(4lU3p zf|HlWhhG@9bAY4XhP|>%rt`@k%H2p0;^uM!&i0JYBdX)ST=L+r@ zYVDOlwFs)?4rX^j14n7r|Id{}t-IAu&0AI}g4QFGlxndb#PYcUt<;iw=R9Whlqt)A z7eW5aiP3=Q4q5A;Q(9!Qbp=`JuTo68A+mW&xq%4!S{|8{%f@;19)G2(2pWq~WzF!K zrWIPUS@9aToD;n#Te_R4PFq&|Bk*uLc4{aEdQnYJ`RnU<;j}+T1Rddp%D1XO)=8bm z>G|oLN18~Ml4B6wJlzB}@_;q#Lru>@`0_|*B)M0nc)cZ2BA*pEN=P>yR6RWZNj^ix z3;f_J&RPbg3}`(j9U`mNB{43yl?M8vd!;HXL-hclrSIm+4QGIsmZ8e<&AB}J)UbE> zU)+!~W{-SWmR73fsd><9@gI4*X=E0V77sybQ?a~B)quQX(V8zFVstdhR`}u* zH_~`fNQ+XbiypXUD3bcLqx{L!QKarN*|Mb9Flt#eNS+rBi~MP{b1KIAG{{y(kvSX& zG`*NJvDA@l*CiQV?LACLDL~qBT2?4_O;gQA5raLkUy@QMih`7dNBVtqj7Z;ZH##y- z&Outor`mP{OHWtdvrHTmMKvKUM-eW!cTdH5WUa0(cF*)~9q$Q&IACTl z$Svgx=bCaLYWTy@drUN{)2=&r_OUqjRaj>eb%fPvcRqBsa$tpjfAjfd;;D(_Q}67H zXq1tzhwcca!P;#WcZhv>tMFR`vHE1ssi}@=@n?!%0fRd~o$NtErF}nQWiqO_o6BIZKTe}m0U4s7);>dE;bnc`QZQl2lamlYP|9{sgzTvF%I6RGpMId zAHG2O4t$V+)922DkK*$6LI2N!+8;IW#^qk$6Fm2oA9wuo;eP#JzWx5EU;gBqX~yYq zLp5rqZm%;0-ku=%MKAsiZCKo!mAL0;;2j(Oc(i}#+uflB=0%szjxY(e#wM^oA38b{ zYK+U9PaQ;>ZGs5~U7WwEHGfy5U#gRQR#3V@8+OU?poVdQqm$9^uy6AWb&}7p63u&l zuy(FDF8TYG?i>kr=FqAA#sbf{&&kfPKSwFQc(Kknf4Foe-k$G!P@!UHR1q*yMXzcvWlzrJumbxU9;5aiFB4vrG zn-d%x(;nLL)4OL1{RXJqM;Adz12MJJP-ykGo|PDDOyyUJeoYew0Z#rD2{t?iVEGhB z(w<{`GX&ws%(>z##hiAMONFL_R2X*GYG>mp$xA~VZ`UYnZ?@%UFbT~I*7Uk66v&hd zeCsBf!L5}g#F}m*HS0au7C7Er9>}NI;Xug<R8v>*@lw2?&loJOsaTAE{s& zSuw$}m-P=jQ^Qyf5u$}evGw2Ia>a~M^!J{24S1ihhpnHth2q#)pov}piz1pOh^yI= z4)Vo=v^V%Rv3NQle+L$W#zl5yi@PdxK~Bcz!mbV4M9KmDSbT z6kb%i%kOJBANSPpO>*Dn3X_VM-Jm}o;uMG~1T%E7Gdp(q>qI?1izT%DE;Se==o6gI z)#_4?e+sLZ+27Y)9tQGfA-hWJKvy^qX?46gwh0hNDe%)4a4!&JM`9>i77j4Dx0j=h zx6`iogyGY%u7z^U%X9UG+^=!EF-Mlqt;p+Fjfn4n;S2XHVN@Z~)jeu({*i;%aIxP6 zgCh$olf+mPDsC|D5W9ae-4xMEx@5sJ&UI-uBH`!l+QC4-dQbAM!gE;Gc0lp0<79c<940w|%6wE1zAC`3=C-0~S}9R`VsNBhOOb|7bj==WgNLZIw|h9|=35sS&b! z3$mmu3(&TiOH@?RZc-rLH= z_J2!nRTVi9JQPFF8j2wU3$TZ#ouyYil|OEY15>i>!2*d*SH?jTu_R&PRe{~-QR2kL zf|rQXUNB~Xj_D8G{-Rc4#GgT1g#FYvtrn>6wd!XLj~Mem1P*6(e7O0LK4$HH!`+sL zkjW+(@>NwRcNK)L!Amtqp{T(q(u%toaAQz=4}ij{Dxb zMKpL9K8Pc893R(3W~>&2B-@Ip@(?Jx9Qn6&hr^ftE^?8ls`5A3$8++5;> z$iwB_lJ^F#qqC8-J|5QP~h6$!7u=`9M%gCY9`Cai_FB{{XzXMM1w@)`(;HoRn zY}M5_{>$Cb=2(sB;Ppp^f;-rxJ+bM2NdS#I;j4T0f#Wf_Eo-H46?wa`Fu=S%1Br=0 z;8;0^|f$Wipm!(hm3vDo@g-6L?bk({ z>7&@X+ns+Qp3wlU$Z~8>wX_9nyjUic$bN6aJ0L#BBApB1p278-Ik$tb!$9v^T@_KU6=b^%sqI~XvuOA^6c5o{P86=x z!`3Pjs=A3LXaB<&6%o&O07bDGk+kDTAdjH6V zUvKNJEPb-b3mped4nvcm0aAYkaYkc%i3-!cRl!l3fMf`hVbIFLy&hwW`4`C5a^Aoy#MZO+%|^E@UGUK zzR8wG+t+=!xw{6PoG&8|uzgs?^oiAQPMA?(DJbzHt=2j|eH$Le#GP6Z+(&~gLTZ_Qd(X0%sje|`SCXQaPfi-fyY{Z`hE?xSoCaa z9rLswq+v}#i1hk8EqV{`PjsUxmx()V^%}m+@Ad#=;HYJ5tB4^OM#g*#dqd6G=Tby{bx|{jpzE$!9bOD&gf2#{m92gbhd2WtQ-(!yaa2+r z)nl5cwDub4vK#Cp9^<*wD^h*Mb43R(Q$q@gG zw|9?c`v3p`zps)uj3LK(wK+_YER95A4&^lD9I;j^bBKC5^dk1kW~39Hh~)5M%4zbN zDPnJv;&te)Ev79=dB5LgM)k7M*7p29dSAYm%lD7p@2}4v-^-uYNU^Zej|B+2!T{IHlYt;=e$tAK&xI&CnO?O0<;FHXQ8f<4t;>J6EL%18_#o# z)XksdCSQV}K0e}H7KG6&3=9x7qxy>1p>bOQSL?9?t{r8CsZtU-6GZj${d$lRk0X9b z+(?-}#vwu+xdS9t_Ypb4Ir*>7OgbvSO@UPOb$n`{FfHYpx@-jyMZok15xY3xfm17F zOk$^)l6+vVY@A;JZn;FYf|#mODH_@zELXP?GSnPSu867P1VcZcaez6oj7L%RJZP*Z zo1+wRAUuU4AWM?>L0>FYnQbD0c<|+A2y)LSYI9=$IX4iP2|<0i?tv0_3KYhCL41%I z#941;ae{fuVD$@V5(2ZKY!%A&{qp0b5%6m;sSHl!6hMU~k^;4Wa}T(wN>z^FYg$?+ z$$)bS1t(u(cK)+L!dx57S!r*P5W9S9SD~J50tKawlBPE7t}l!ys+a<`vC4C~vm_%2 z%w3;2D#=}8yQF_@wq2T-%ZXKi0yepTPYIUTBp$dG=#+fPj=5SDD9!F);|c}rDv9#v zCRwl8uD2HwMXLb4a8aNh*@PI#pl?n0Ahn<3vq4c;?lfsc2Rn^tOTp@SM8sYO>u2eV zNLS?k7g$5Hx9Wm^FWq-w7mc8A1zlfDSZQC@2!Sm+BkemQLVzMLQEHLSfo{OI1npp8 zd7X~??+TkO@;gody@kXuHnN3rY9C zVe8oNJe87^Gu%D zuqA=u+DKai`_cW80q*UG@tV}*Yt0j+&6Xwd)sQ@}L}N*TpP340*J^FY zm=C+|c(CX@w4YO)8tzmi-Di+jnOy~ z2|BHI2ktiw-FfZYrr)l?{NnZX?-VlvtheKDd67W*LIlmvt-S0qI2WQ$|3Yv!NDVkw zZ14>I&<-vEy~bez0wf3v4we>{zz-kIXi)^y4L+5w-poZu^&-_g zdRe&_g`2a$vMnd}g5^tq)v?%W-`=qLug7-}xDTjYDx+I1mOQNP-!+bt#^_F@r5d@V z^qJsGT2+aK`=$2IT3>?8Qfln%WA>674{v#1MU<4N+z-=}LmeWN6Oyh$N_6woWR5_P znB%e0s_xcTc0i$HVSZwiy+on7#j!ouoE$_?1gxJ!{`k;?${&+YjBj6B^gGzz z_Ma0j!O=wM+}kr+$@>o*>2Iz`_P!sWA8=eBdu;m8X)BAnx>?}=vbe^E#iwZ+rl{AA zb(_Bba&WB%_rEb8tzejK`|Xuo&2t#GdA|t#Th!0DK8IPFh26vby>LZ8^tJE?E6BIV_d7( z1)50btc&2zjBmu~=bn%7ZlHQ-`FrdS`nl%r#8K2S>h@D_@HZ~r(lo^FIf2tL*Kh}O zHqF#tr(FvPhMP;zd|AU-e3Qx89~D7B@5R$zf8M4urwPjOS{ng=gGpY%9bCcyb;tUt z@#`&i*7S!=pm`yB6aG7(4YQ7B)Ce2CUsSeW zYG~G3H>^vW+*0n~XY`-@?c3Er&4=yf^ASynK+@3=1=Mw4f?jPuht$D1;(~RVZh2Udcjemo*G6`%1$vgecxt9QImfVyp zY=w6{NVztHD_g!fxEKEEQ!T;_+j@@GfQ)PHwnu+ zbW&G5|GE2#r_k=s8xI8Ae`^Y6=0Q~3C6B~-zdhIW%&jdMugg3;^$%sZAka&H7&H*ZSxQ&gn8Wj8-+&%l{kSBf%0J9BLF7qhttnCIM$x=B#E zhnei=OE3FA-M{NzqSGq1pw~)P_|U{0mJrCxHMDY%c@ygYpHiF+mF{!0+2?wIs~MVQ zIm1Ipn|{`*vio`SITLgE6OFQDM%Y|23*J4B5Z+w6?@Co)Qda!RsslDY3uouN&0CNc zEH&PKtlZo}j@KTEFcQ0K=TG3f#}4%%vvom3`r?Syi>TUmW^8Obt3MwAyTmb7P|I7p zne$;`;=QGtGaixUs~y;Sk|t07?qc^C6Yu8cyen%xId&b32as?Kld9^maWZvYBc@V(jG1d4XzejbTbEO*d&1OCdq0owWaL zgzL?<*+!Lu&6#3z+SjCcyzKhVE0k72qgb(c=ML1yQDiD)h56)M&a4FLzz2TWR|r<{ zMlFyqsW!7e?i&pw7A3>@;KR}NPA^FzBqDe}0FR&Sn#VYzFiyqSR?EWDr ziMN*IQ5MAso*ir(4%?_I{Jd$AGn$Z@I43JtQoa(p#)&@|B3}i~5HaXMp%7zEBYxV`fQ7+~vg<6t8xEBv0n_ zmpnwD0%O+uOYRVNMX90`TXFhvu}vNe*Sv@-B{(<}6>JevtO50}DB!BnHFbS|QPuJ& zIEDAEI~4$yZL#f-93Xn#mSocWOJ*pG?PALHmIWuZGFG)}Y$lpjv4zChbv#8u-`1}! zR{{qd8xm0fL$(wAh;HemlT1(;3lc8i+1RuqkwFdZ6yEBTfR6vQUGBwwN|RYuI@&q`wWkh)H8z!oH8Ol{cpiz}Q((?9_vR^@StOi@7^ zWhEh6ZlJm7dNX_5l9n9v6&$EP zNg|$(;fBq$k_uS;Ochxas$*BI11>gW__vW;Q>TOW68ae(xJkM;5+KIuh9SZv9pu?u zcx&$M*D=TEXlvp)wIIVO?Lj+JZJH2FY5`Y*!PZa5?x@*!*hXwFxWs{7L1HWUNH+Vv za4a_Ict(a(=sOF`Puz6hWVa8x=;s0*gJV;Ma8KaR*2RYIVB0rsH6g{Ze~r%WjK3U% zX4I*2$09OFEhkr`ogRaKyd_?U{r7>R!i4UNZ}NAoGdR=ODxqdaWOM(wh<1d{hpk5X zhtrVLjOx{n?P1+*&yrs72PQRllrwH7+t}yU#(+B93>V}2XSiuHny?#j89ow#%+N5k zD<(fW+>3WKK9dQk*G%HrXaFq+E6!L}aZzeFj3&4#5EV zy9V=3u_rTbCD6D4I|e(j`B^+=nD(#}TQ`AkMN!$!)(zj~6Otx31T%^mizB$S_Y!tT zHG-a$u{dztr~$sE9vfr4F&Zq>@x{-~Q~XQxk>gai@3|KJS3Mp(L(1om+!ljx;j_mQ z6vy!i&bxol8Nlp|*SN!#Z?Tusj3STUMdpqLz;V(RVOeNLsU?<*w)EHRC*XvMG*L)2 zqb8M?Y8tf4C0AU#UFnE@jBhJwosP(R1OGu2Y&=Z~fG0k@Q3J)bz4Yv0JbbslF%kq+ zuw`zh1lVaeD~+p~R;FlUeZvsz2pu%}?q9T0JZ*SmqL1z{-i0-c$MLoN&(){{f-+u|g)Euiu{r<%rymx9NG_?Y`F6pfrT=zy2Z0-&N z)@2+qh4ZnpG8;~AK244U^}r1yFu%AE{h1K#75bAC5C14WsRtrG$EeoR6@EuxW!;zd zgT`em(?Hn2@uuYw8@WtT%fmAc5cAeQ7J384r{YZm&eI%VUOM z)q`Iud5Fy&wd>_n592+L^l$JSs3&hnV&*&QZk$Ti`jbx6YP+N>5!WrCZ#={pVitYu z$R!?;aCUL(V*lMuv_CKV5ehh}_Yj~uN?A-`R~?b{ln&hVQ)+itNBLE1TiZqmTW3Z` z4y9p98ZWlqS*$3Vr!Apo+{ndgR=F@Zm(V6wKjxI)3Z*;6|b?jG{|6IAO;pZ;dtC?yB8`s}DZm->T zt)I!eNz#rWpT3Lyo#sCpGIcuSqt(WJIwWLZ)dT0V#o(kqd<{<1sl>p{V90+&?%95E zkH#tVYo8c&s6NmSP~$&Y`+0w)h5xP>vN*oS+F2(8mVb!i^l;jq5cFZF_1LS5ud%o0 z1Mhmke#~)8cDDL(?Cxtc{=eyVn3-GTZlBXv!T1s$f+nxCKts14>z_KvZctndE>xe* zksy=40sS&;`nw18Q?;MLFE9H~dtcPN5V^Y;{pvvNAHU8=X=Njuk>yS9xGk?wF#=qi zZkC4}yIAx5$;Hab$=W^p|K47<&}!9j63~bhIt!;d=I`pdYx(G#n1)=1g%|5ws?^<| zeC68J6IR?xooiQ*$m!vH8=$9jOb>6g`cN10M8EmM$x)Y0FtbTeLia$+i4i~iHZZSC@O0rm4@S{ znCnnYeZbtc2aiXpccR91fP2mmMxEKykN|UbYt%$`mlf(PA+bKDpoHPnb^ZCbb42-dqg1ocl?fQAN8BU6AvUjp#_NRl=f7mk(O-U#yrrH>6Ma2k4UV+e{r z#rHd`NHxBh<4w(Ipr+G~{_cBC{B=9aocyyJ$cXn`@<7-(A`Hvo);?AHa8v3;93jkw z0BS3=sDwRpkFfQ|hM>I*gFHQQ3}Xmtpc{R_vs2UBT5O5|9y|sNw{yGw13b+FywpLJ zINflH6=d1umT!9o=K95WG3p4n?aamg z$0+gM1y9k{1IwpE%>zq0&F?I*_yy1R?}wf3h{Ka_^tK=~FmGLy(RiL7{;OveHT2TI zXvJrE8T!}GE*Y0epBL+)K7l-vv%CK2wBrUu$E__MI_1ai`-W3Djm>pjvvj@mQ?I5- zcfl|}v{?7fLOshcy_9RPRICd$jS5uGW0bOIrz5K#?}4W&h`{P0rzb7S+ro`O4&Z3PAb*QL=f+tmS1BYqcGxZrF+SXV}ppX*CE)iz;_jegV%eP}^CF^!^%`yp; z_DRrKRP|g$AO~4EDS(kjp;lxrvw6_Bm=%G#mq%2C-=_S*{629)njpCRv$S)tRGiZS zg(=(BtGvDyg}Oe8$4@e!fS5{XtsGJ&mI=$C*%J^4nC;|V-*&4#ibfJ47N^gw>u+GimFRc0JXFKQaUG;7}N<_2rBqxkZc}iwlFM za|CLKsj3T}a`rU7knV9J-Iimjm{7?m6RTcpigh80{X(Jt5jdMv*HlbjXh6;KL_OK1 zpY8jaRjde8Lb%PJq0o?8&|J)s5I21VEl>^xWY|vZT+Wasj2O=c83*QCLI-YW7DOn( zwqDRKAwWqNbJlHX?UhyQL=LoAHY=}5JW!$#_m>tz?>W9J-RfdC`ezhL`o4Fe*py>! z3HSoKmPOF0>wJY_bd$lcp=LZc5jd3+d)I*BtFrDKsicT)s8}twx(=;E`S7XPwds`G zYNZ_Fe6K-DdiTz#+wTN3GgE_e(@5aE(hN0ufALmjvb87HhV|aw^`{6R`L@-*nWFlM zMK9Vx1>kt8eBcmZ6le@B^a&V3qFP7?(Ho*9cgc%u{o_chTyEav21%fmOh}Qzey49I zpA|q52Ubi?LnK}nH zK|sX_h6*yEW=IWkQV>L!i6fUeYNg647!qr6m>l)}#|*FEn)Xv$W|gqLkh*H6i2106 z&QlHc1w-F|ri%HgN(`)L3d)*vb|n@RQ9~`O>?eqKz2H-_gq|N|D`Yy4snQ6Xg9cSj z?Ua8u%(j#UFYO(=4eo&&%IRY&l4iiSlBuh}y@V2&=$TnTLp@s6_0T*`Ss$fTOV;AM zCiB|UD=87rrI19T4q#OgRGaRNQ{hZeq-#pL&Ug*n#$U(P2Ph%goD-TYqO}d@YQULeeWjx(hcx*T`lz-+o%7RC`gw6qc;rJqH-p~NaL8Y>t zNw-x_vVrW`!oHJtd3msqbq9jy&BV_XLW4!3RQX^taIcQQGl2E2vsE~HB;O$#9_MGU zsT~oS0Jo#x@{OsFn(pcXMM#GvsK;TF(Jz)GiNLWuH6@XHc6yp7ss}i9wl;VWYSlvZ zw3CkG_5MDgv^dc9Tgi2438@`Icwq;K{XB@yzB4E>LcfnRzu+53=WoRy&^_=SX2nI6 z!}doaCC#RxjqM`v4u&8JgW!x#CNkHkECly!Z+thkmrk8-j~?t<=2A2bPNeIHuXj>{ z*V~=^o%*7Mdb=N~Gty%}hjU{LCcEo}?Ay$~VC9yPK(FrLuA1&zW05v6^ea*@&m5*f zFHPmHNs@M|L$aH^25d32K7z6y?EPBy1J`QWTWsLoYvzZ^lg)K49lq~JwjMqo$_(r8 zjlVkO`;m3~_=h=%vuQyOSs>1TAuiN~b=!@M<>GOsA$D4(wkgVCq&8Ho*C<4TQeb5eo^zq^+WTm{w1*3EOy1{wz#CR+?!ufti@0d{Go z85;=rkF8#R<*C@*@-f+lKglF11sCBgE0)jkX{?w8+8-5V7j@d zTS_8!F9CZ*xVRFn$*kypSaIhj`D*v`*Cl6Dxujekg9?8X*f5ddLv}4rCwU~>U}~aC ztQr!CNca$3eXp4W($RJqxEeVh?$ilRU{tL`KBc?il|CCtnuaiJSqb;m2bH^xyl9m zGn#pR!*F5-mYOu4*m?3ANIx6K9jkVHQ>WRQ^^o?uRSP_SDdsf9{?Z2{4P4;9`tF~C zS3f`_Q~VBosGPi+ykzURg&)t=@NyB>f?wml2xc!09zh?ORdF@)bcLA&f`mZrZNxH4txC7HkgH}{rICyB=?l1j$aXB z&RgSudH?^IHr@V@JJS{C>h^y?-vCB*GVx{{07 z5KNBo7^)HP+5RB1=aKVv`?_|Rp@;V`&2Nt-zz!5yLcN=`Kz+ub%Sx$-v+K1#vX^I`6lTa8|tX}x}3wx8Cct?y@2sLCf!J?*kfX6^`czfp4y4xobc2o0Di>eJnh ztE9*f5Y~s88F-+tRNysFd6$*z{4yR#Bi+(-e|qy^79mVl@x&_(WB#@BblnlNiu?X% z$e*{IjnqtD`iLL26O;TM_2kvusqozrC*_@b%U^l)36GZd7 zvKJ|KQxl>6XUCrlf!}Q8-6cOmnCDK+dKC9TIK754NE_BBOn~Gi=#K^+GK>qRr6z5s z|M5$8m|tC6ajp?AbbGnSQB2uf1K;l~0r^tg9PH8KKr5U3=8Ops?PB&@CEx+cYdq9U zYqic0grMH&CGW%;=9*dkQm6lS%C-PcKw&OPxsq$~V~~NhWt&|gE+F4JFD{i8G#%5# z_xn}KFx0BC&A^3vG=&i&{T{W^U+r)5n6!V84S!PT_oZy6q1NvayW;1a(g^%S%tt%~ z=RoTqTeO}FbG>CiShX+>K>-r6o~1(|ho^^@(vZ1Y6ZpQzp~cx@jVN_70!*FdmqYPa zF>?PF1NKdzCb5Dn?s#N4@DOyLqm~+$2LB1TnSv+C6|7)c=e&?+Y-iIdIg0{L!W zC1Pggw9X7krrLW2PQIKP&F9Hl=!dlNn;B3(ZB@<9^V<;7 zfK)N1N+Wnp#aTV@3OJM0A{kN6k3Gx}`sVq3P)|m8ypqae_a{2Yq?=-%?Csd4DvL2C zMwk+TX$XWvlGM;@M?Q0Pzl(gZh;zbHu{C;V$%&j9cbpfW>KLA2{0CDe)Ozb#`tGTZ zwC#h@GvnI44BCheMwEVQ%fEodMU>G;!p{G+55azey~-A`Mc?f&>8}6%2wXGYjW3ro zfVl?22E`gWTfx7NQ^AKV(`O8UWkz!caL}N!!;cW)>)4}g#P`pg*_y!sAmxE{L)xKj zAn5;zYkhs9jCK%`e|0ejBM-D%rJBF@v4GU%NrbHaO6yZX<0iVnX~YI%tDT;YabJ4* z=J|$?+45=1_?0*Z1S{Z|B*T&!=5oYy?r1 zQPpG$2Cn2jc9NSkF6g8A2o9tXDDAthOwu<}wVcO$!Y*4lQoPv{N&Q5njzK(y1HJ2) zLJ&g_lK0KnLf`fZ<|yH1ADbMQ(9Y9xU@qgs!dPWOZa_yS7TWHx8DTTBtCNB4H- z=g-QdQVJvmX0^dJ=$ohdl_kWR+yLnoD+e9f5+yIdbt|+oL2MD*JlNH~#=Ad~qiW#D zjkDhgRKWKIsn;@q7?b^wqSOPLOXoyVF+^&CTIeEZ)v#2LlB7s_A)CopP41eZysU?s zuzQPqneAvO0r=X8>TUhd;CiP7LiDMt6fI)PAVo~-h8|e`I(hFct@dS|1V}c`>%mO* z&^9%2Dw6^N6Jq6jDkg=Cw>`>I$Fe$nXtDH_6GMbXPs}PfLTk)b8<%`GtAVWayM&!?QEhNqcmdLrFW~ho}FXxH5 z2v!>isS%|`?c+2hqZpi&^023S+*M_M0l zhE50P)|{P*3(H7|;r*o;vA#s|m@COSquxQkb6nN0obIY7d$Hm1sRlfjGIYskh(G;+ zoO|>@3#HX48PL=7+D3N+73wJVnR$W9*xAv(3j8Q-YY)tGpYEq>{M4w1ImsAb0cTCJ(faY&rpN5Vqm_5#51tldhfdSFyF>9~x<$uG7I?TPu zkjSS#55(A70{MOI7We|T)8ECo(`(DEXgTNSCZ;i0-=5If4oeTWv@DUi8p^T{3zXZAgs~Jd9B!rrV z7-|bi*dZZ%K*t{8Y%NOl;g*D4rk!9L`6LHx-8I>YFUg41GMOL++yP_*OkM~EfP_QP z2+dIVcKl5w%@^jYb%bvA^z%ks`8<51hR;>n&I<5`2<8mK9Wd-&*uN0^$Iyt4_P|yZ z^6~x##$A15BN8K$#!dD2CScnFhkd|Tf`~~g5O+)?axVga@LUts<-06O&t_0u^ z5BIK`H+K)8O|3Ee;o)IRokM@1dfuL^W!^Eka?fWPg!kDLo3iD;oe%Syvi>+ZY8CRy z`(95+x!;vG5>NNYrJtuUew8+dPMpepwBaNwc)_`1$8+S#BXu=>OFg9;X0aM(50bNy z$=k_w4`D_T;>PLlh>VApx15jfyzMpKL)Ca)WdzJ82}A|vfWfvBEkeZ>L#qwOez5wx z#u{#BK_-bgorafdOad1?2OSD+Q{vOQF6pfm4$riO-l|aKtw5@gezpmknn&0eWvOaKSl%vjA0N8!_VIDLTOOq{9hKZ9y++s_Q@V9c(xz6d47=qa zk|X&qlGGf@SJzF0`77q}#6%}Gq*k&96p&J$yZJ|FW(g4pti&m0wBSHR#-8x|*;^J* zaqF!Q!i!He$UJwvGI+3zCBzB@tL@DAc&ocecQ9cD{B5lf1~Yq&*3dmPQK(_o5c=Al zgnZf0L%%osTz~5MAw2T7!MT!v34D&mw)rQP&iBVh$1esHyKC4s=N>JK3ZlGTGABw* zUe?qFEH`JHnN@yiwG6g_MTI9TP9F>~aE?IFX>GU(#&MXbH@G-7>YygM2q&z*c36?t zcXO9Fm~sCuZr~>G#$IHn11&+9>IqC#$hk^?m`rEg*Vp=2Z0S*vhL1k#EEo00`$^9j zE&ICJ!89{Nq~z8I{hwT{Kb!6_eMwIt*L-P$ZR@*!bHi=F)5x=0&iAf$4A)h_!mZH% z)+yG?3I`n>NRWpxPyVQ3ep)jf20$dA?hgO(y^yh#!78H;9^T5P!aG?(-*9u<@Dlvm zyYt>9BcO(;PE0fPGq^S}aSC|w&V__iw*&Xpe$*Fl?-0y+@NG>oM{io;!Q^6!8r}#p z7oG>7U%Xis3jTsbt})%bsVJ&-nQyU<((crA08ya%I*oB_5Rrtfn@CAZTPG)Gs%R=4>r7b7}Lvtb9C ze!lrQ&u{s`oxR-;u5G-`?|yLW@OIK+^x}g$RzTL^-O)JrL0liG zF$f*V-WuFG`)Yr)5HD=5%`aTX&*R@+5>=cXTWXPY`HGS6%tAT~qi3UOp6N z$wb$z-uK;a=hqrE5|}XP6z0Lp$r=kFjZl3Mk*Uh5xk}(L;te{eILyJtRW4$=yG&V1 z6vVIk%WpQTR{FzwV|k!0Na}0#F*zV`ulM53V_Z$Y{y|qI*)5w@&+xfUvbr$8U5uH0 zhV2a;L8E*0Cp=JhV4fm0I@(s5z*Y-CwzQ<%y<^oC=82(M3Plcfow;z9kI)UNaOQ|_ zP9LO-?M+a5DQ1dl6ANT1`9iT5BpJzI|G1w5tS@Xn_9CuNFzES?&r@t$d>fHpm@k6P zN*zo1%}~;9dP$}tM=Uhz6wgczLIbgHv!6~=0Ajf71q4adGq{=rVPAHqw4DOQj97j+ z!04O1lGoVRSXdXbP*T0G`kB|WlzgcT)K&UImB!&@4)ykaFo~*3Sdl=G$eOuQ zRB0g)Df@YoGX>0>Fo{Z)yR9iEN~3{8#>#meP8@lC=hAL%=)oG;bVE>?Q}*NH_qFTA z!;-OYCZJCuowyRe>P1xK6bYf#>H{*REVEyqt32m_hLF_E#Z#2CekRrl$#I@#U1xi? z{G`iKtqF*n8y_E1zU`9DW!;|H(8p`u!C~6$Q9-Gl6tSdlXKrr+IhUs-sTG2O!bFWj z+l~PM)ng}xw^;K1`vH|;z9~UVHZP8h%)pId^`LZaXwrj@*fCv1bGpqiX-;w@ms!~uYQcz zE4nAHorTu^oI0l`&yJ~jxU{zpc|rUrsS1)(*3X!LW=9SPu&l^FD}q~|kJ?h#GH%#I zOQoD6V#vRfKNG7KOF&H|`$tHXP9_F%GnJy5ikrEEH+FG4)qUvkpO@TKH+G6=^N7%Y z`~eRPknn{A%;3(Qa$Tl`qH2X|OvJIdgOkg>(5bwx&b<5;%9`%!E(u8czqKu$Y$rl1 zf?m~LW1do$Rw~TNoqoNZ<^>%v3Zx1h&saA7IG=cqEXav(uMu z*k3-hgW<_l<@O(SSM_I3Gsfl|D!T7CGB_kh`Yqgw+%%Y|7NiQ`b8h5s*o5G8)ZB&A zp+|=imwQ8(x9V5&KoMa>&DpTP*}?}5qvnwS6hE%_xHOV(T+Nssh~>3*q1MS6QwA~i zDo=Fhp#r1S(KYn@v@N5|G?3g6TkjR&pLtA|e%_o~YdjIP3al>tK3%Ynt9xD>$g1gX zZ&PJ+%a2!p)(`KCuOlA;@Gbh#=jc?^DDI~059~kTTR>W3L>mzoVhiV!9HJEcB7B!Q zSVs`z$e*9)5e`faG;lLC%r$EXQ4y)N>uEYWolk%Rq$8|JuRxpeu#+?vpq&hp0q;`H zv4#o6u)_FXSeh7Z!HPYF);n=0~SA8yl*4A-vPz>m`nm41ty}gN`z*kW;ZvZjZZ$@#!1%9a{ zE96qSA)HBy+=Q>RFm!ugpJM*+Y~X-E0{=D5yL+N3ciR8)tEXuWre!!Q)Ud&nPIa6Q zx>#QmcDcg&2B2|$|243?`AZG3PXlb3wWSZvh&GYpd=EA3LbXAG#<>XlA6zi*Bxl9p}b@1N-)G|^ezBnZwc)GXm_@fv=f+HUIplP`+u;#Q;rw`UQ^Z)eo-5qDe zxKega_6*#fW7R$g%Y`@Q6A|IC*U3HlNRn2!|F3^VZx8NZZFyv_uRj_yTvR2I8{Etx zWwpU`NXeG3`*sGBb2>_%J=?Bwk4g4E&tUzUVRI8+(ol1Cu3@qnc;DSgh9vs~4cQ5G z8*L`E_IA@UoKfP3CnJ2Uc7Odrp3{r+e3I&ceLOt|Hy+Ur`vX&UZ9FX%*|QVLzGThG zOvEV@TStzm@(Ll&!o@@^=lpe!$|EjiV~YcaKumaApae2-uNbM z0SiwphB5MV_(d?bT++wwg5N7IUF8~Iy6z)`GYnyS-g~3I2ts$DtM|BWp`$mO-SsXH zu{3x=ySRv^%`XEaa|6{)W0Rj3JroZjIl5vG^5#whdPO!UPH?S6i&~2r)xP{F!2Q{A zZ2aEk8r^<;Z(hJQzpl0~p?ocUOO|L2=1zq3GS7!4SdYTl6@;;~%RIQ)GLRB@Uz|D~@HwqJ~3zw?U+x#scUD%%bMbE6kHaiqG&@78FP{Oi_ny+tkq3 ztB_mL4uN&dr=Z(v)w*Xfq*m!azjI$A$q<93#e%~WwD=WWJMu<17}QG@$4}<1Br)5F z$zE!xt#uj7=vwB8XTR#L))qHxfUha?uOS4G4L$Hg;Y8G zcTq?5QX~Ke7=%t1nG@$bSGnm4sWsiKHXW3-Tofzk1`AtLFw_T^;ZGyAtSr-=KN9zj zUPydnXb4^<&4==$midSAn#Qi(wR&`zf89$r)cCp`2v4{m7=Aq8+f#NoAYHLQGur6q(AMeFeLc-!s7g*VRTr0S=n_II^z(e_6~47=-`mlWLuf&;8z9rfuB(JDYmP z$BMn<{Pmii`2=(TYlEL?Jm8mmhCWu#Z~q-@xTnYLXmp*vmB;oyR$p!A>Ml3GoYFBC ztYcy~AXlC_T-CtYEdAbCaaiY>%g?g&|M>IRR2F)oA@9iTBIKSEk(Pnz5H)2Eh4TeW`P$LxDaO zZJ;9Xqh0^D+AM4f-S6Y`uo`Yn$*?9erQ{1G3{C@lYK@)S(EwD*0p-5{+Ck%@ z)MgX*`N`NuJPc`njQfAFaA4`rZtE)6C+!OP4!2dK~nzW_b6+l-K?aRNwp0zvKM$G|XQ6V(BMr^Z*+~A66W0h6O%5 zs|v2U?xaVeCXl>JVDVNXZ5-flrD~wXH1koKIY8?pkCn6n!{idu*))rw3BLj0mf)so z!p!ICfM3^R16X?p)BoCJ-4ugH*V^EG=ie0TUX5I+{^S=_cCq6Av2lyXK%7H`Q}>vm z{<<=8QPcO-CckYLZy(1S_knwiZfHdUa0t@o_YcL4E$=VUu+;tbSp9=kto(#u|)+bzn|5PC1%*_$RD9I;9OMX?sh3^~XA_ z!WW!o$31T3*mCkj`BWRo5o37i*s!sx!1<$OP+=2*Iv;ZBb?{cLTGgh#=)S#)r8|v`_ws z)yX2*0Z+a5oMz#>^|{Iu@NTeX1j`*^sHwO5QzJ!{mf13q$?DGljI04xzkM-p=&b8z>Hafw0&Xx_UXGbQWxVbHwEFPv{a=heMMkA7_byb}DzLcePwIjfMV zVyq6jK*ZMTP?u*XK3m^5}W`v?t&5J4Cicu7=pTo%Kj+yiZW3Z>Jt-l-t|(r z7%#;O!3|TNy1l|ZnrFSOc}5tlu)e;cNaV~Cm&LqJAc;)IsZLmGKw)`_DS#+2qW6g@rOX03O4tvbK@x?MmJ6{&sGTQURL0BKl%I+rNW-5p zn-(@<<*>H4CRurHwOcBYtU@ZaYON`zYXCUw)>ubzoOnn@Du9+2hCp;iWrCnUV>Pl_ z)v5_#FgrGIWRR--tqosK1`)sQRY=tUr@RK3c#mGF?|=@68-tWp<#PYZl=Pa1fT)US zfd-w#GscR19;9A@CO2``zVqPLDZCGyrwjdRlhkIfv>D!Fuj+skRFb|>uPRiG6-FM> z{jIGK+7`S5F$pfmtCcJh;EEJV^8))gbtaH-aT}DmYW!6Ne_^6$#qEkYiqa-A_KB{d$G=5A8}wB-coqtwGohcF0$(1RO)^wb(C_{ug8tJD zb@mqK2_Y!2c`|0LPymrvR+NbjNwS3KNmf6D$KuEZ0-0ssfJZl;5yc2p8AVmSP$Ff?p?BG& zi>c-*W)*_~-2k31Ri2Vp5G>M0IH{+Wb!_CD^uC^0&_z3(+ zZ}V_VZFD%7&=#*mI7SY#IIIDch`1~xQk02Ia=OiZ<~JM%%*O2$d0$NL43-;ci)^HE zhRijE>9I%S-ySVF4_XX0@0I3GZoV;ttx3o1VD(-ubG6?!W$*N%iTTrypBEf(jO<|Z1@C^C?mJt_}=4s`Z&U zraVh%P_Wj!q=hXXMCuPx%&sYv@I1CNoPY(bl69>O1lGJqNn*PT`U_?)?b<<3=(f&vQ!Zg>k2jcNn1wTA)v zwibQpFk#nNY#cbv;8%tg4bg}2G?~>kWXiqy6Qpx7$g-=!{uwvJwe>XtV-Lh>yt&7K zRD`Wb!9FJ7#vTVQ*-G1zw=b?vhrYkh@6Y7}e|v{rtkfCie*CVkn~gBMW?L#ZE(Bu& zW>ok?izUoM1~8hubbn(Z1;}j@F0#=$qw`>sl@)gfaH08OX}%geA8|E7D~&&m>uv{( zad0T*=QH+cDMnTjI9;W&e85Ei6V~alZHIZe4&(gRAr4 zw`O2Qo1lLW9{5eOivLJ@Y;orUF!I1@R%Y@jnlGH@$M+ol!NayqzxD?h37LhZ;c4-~ z$vqo!=m>$upS^l|+QDRdk#-JZu(X>8vrGsY(fag=HF1*Q=XY+SWbxPe%_8x0Z$e}z z)Eu9CGU3j#rKL=V@~@|m-ZkeY;_Of7Kg*_i{A4p7(xZK{ZK=<~>JvLR8#y(8HWD?~ z6?_*l-{IT+=B@tTBL}_za^bK0PG*INjHCF&d#<2{WAkJyi&}6-9#>-*x9GVQ?qCh@4p=(1vKr0QIlEp}f^uUJLS62=A(y~zy!{l+uo zWk)4^%*NZ8=KxF8+w&_d8FfFiOQ9<0+x%B?(e=E#(4ecu2|oIv-qXQ7KmQN&G8UDH zFUB`hG)59=F1X@fhmT~LmA&&$DLuRA%A>=LMl(rP4#IHgEsNpvt7-7*!ypmjwo{{+ z1oNl67+1ekS^R$cs)CtFf zi2ot~J>2YwwD;Q-{Nlo^0sY_rdZztz>objMyG$^zhUW|=+spMlvDYPT))nP{qO#Ff2eY_}*TTcbQ0_g}xiQ}DjjanA7M9zS zH2+gW(!aW6?weVQZi)mDXyAzhH?nx%dAtZ|P2YBls^Nrptj5e3D|9_$f-o~!Jnka( zv<7Y8wbB|L*csem0e%`+NZpLyw|Q*%BLGF{qp~+2k?CX(T8vzo2*Q@(dq%8bV5LN- zW^$)0$Xcn^y4$eQo`rJzBE9;}_Lpt((E&2JOis(+^nFN61Xno86h)-k2=i=cVe$*3-@*65KhBw{boiNP1~+Pe^~oBe+K($ftuYc>MH!d}Dx_Ra$^3@#^f& zV|m`~Z&NMyCl4~lie+8FwLwPrG6b6#B{3WW%kJl=WCpUG^XQ_(wAq`X(HhfOQ9O-Q zhL<9iYjYZF6Ek~2GbAyZxQJL)a5#uLZLPqi{Bg`eMP5*Y=9favgpCE9Imd8>WV(fH1h%-RSrxTD>R z%I$X`T|#FfpKrZ%gC>lT21{U`USNf!^%xkHnFD3lltL2how2wG)}5)UUsei3!Ua-@ zb93Dj`V{!yv+QNRTp?9UTbqa~_bag~avmfQG)~jyYY9<=d93>V{_v9{@!+X1*G}D( zMPcNrPI?FySR;lALqdAJT32LJ#oT1R2M}+&B_6S>{* z2=TENgb0{m#C+s+sHN1S8JyxlRv%JMbyH%afSt6Op2Hf4YGf`ntzXxHFQt0OhXsX{sn-sA;E!kE)h?XHMO8V{8(2tW2a9+e^-~ zq=0!0HVYs+^3m9koAKBoCfDMzXKNKyV7W@BP`cxK>wA=~O0W(qsNyP>(8oQvZY!-J zj<}<5?n9S~l2kP{cjFqGWr2jAGy3r7oOY~_pfx9>^5H}X8Wk$I(}k=2z=SHNj@3TO zDxXM!q!UdYXi`*aF^Bv0@FCeD(516p)*RbAOPt|RKCfyQvUnhw59QGVfJ2U(1x-EO zBOyvo_1}e{2r~%$UY|1YstF0iTJ)a@c@|gu9ORIA6eRqGOOL(Jf{OT&5TzcE2+74F z>?iK^oH1UPl&_itub&YFV(Rjy4});KUJ=A!5jLX1vWrrZ4w#A&^d4-wn)P#4g}`)9IOzdB_75v6^ZyXDSo3??S5zKL-S5)&cJp zhdh|vtBPn9X4E;!7ZrPcXz%Ej@s%o%WutG;`(gfC>YfT?NZoU4xk}EJstRH{)X?fG zK0i6ST`v1au#n0BvR#tTm1MJ^ZUv#KnGEfWo`5)h(3_KY)psX3qwUI_`?icFPyBXI ztjz3{v&Nw2MYXMbT>_1kK|(%g$5HK<`5oeb*?1zhrt?N7}QovWvmvV=5`h{gP1XVO;RH`5@^aNCO^ga3Xr%soL{s^AczPMaP z&fs-%Wvj#0LDfvx=_`y19qSl1UoKxvo9@nC1Vbq|U@^jozaoeH9Ux+Cmo$*v6(DDG z=Y)%plqFnV4M7Zs*`>Ps^H}x4c?-IVF0=32%+Mi68ET22=g=(U zb?1THueuUCFq`G49uH@1ey)r7_Yc!34(bC>|K?n8kOPvQ38-2E9&?^fM|9y~yvE5w z9qTL1_MIm9XU0$M&07wSlTUzsm&RzRq`n(f1GqWB%E3okN2hNB-7hKhD~^U)MuX(m zae~vR^FRs~II_*AB+m!z!Y0k+n#)+`l^BDLm*Fe?booC*Td(|fl?RJaBxo(H9TH6k5nHV+K^ z)`>^_-)v5Z(bxBj`DlSO2V5Vz_mT8RILxCcdO}8qz@p+c=Gu3TMVqP#oL-w4YqaN6!he+FVfAaXKH2+lbiy~k%kSppdPA@WBsRQ*qM(P z;m@P6q+_A_#xL#{g9HNopl*WGQ}44o0$V6psV=+&`~0z|ouJA;cZ&O2Wi@ZG!i5S0 z%Q!b{VyzY%Zw}cb*Ob_40${I@G`5v4@9wDfO0nmCIThGha}tGn``)O&+S}E4+DXS5 z20vngsg4EKnR;61#ZP;N+*eRu{qN?P=Z?l#o3qYP8v?h%pZZj1#{B03TLr)T%Pj{C zmi>gRZF4pH<%M6G0*Ccjcin$D`d6hN1Mb-ObI`4Q4~tnoLD+0RUvgsEk0)F1TlQGI zGCqAykx*QM3QDTR!uMU&{euzc?>PB=9sTO-BLV)7ecsI*sMkN9o|u(|?V=CtdpHzk zf^|X5qq~%AF=3Ss>NR&-U%_H;QGp=Jy+~J16R>r(wCf^%NAG{%ZUTB{DB(~9Tc987Ls5X+coXqSiTU|&{8IzxyXB7N z>BR6@zZ(f#pG@k%O(5&n>1%)gk7xZ7?eV_7%uUr6+b?4aD?q!UnfZvB9-@Y-pK%eU zfMxl9xY$^H;dTP)%y9AWK-i5(m@|#}`Wr2N4Z4Dq{V;K7c);_V+qHiTcb$1#|L0$C zb@sdLiyE%>{%>h83VjR|jM^mDAFznnUOc^mDrSG{GXWIYHgEt9!l)e2X_$B}!f}U} zUtjdpL46=G5mbv=Q+&0P87z?p^V^r;^FzZogVprLCmLT!j9|x)R3z%hrw1%7w%yZ3 zMqz8lgN%4*b8~ebq5Qz$dVJO<1b)*E2*5SdI8S~I!Ik~(5(1+89&mW30W3rVNMa=c z7bj{!JEUtK!^`t;CAqVwu>*~)EC7TZxAO{nUz}}Z@WM(D#30_-zl{ac=l0^1ziUXi zl9+*`yOR*q3sHno0}ep+y)mTddAAGvZhDjt_89;(a!$fdG}W>tc({(Fm2mK#C3E1u z!PdKMqk5WJfgia3tM}*kb!>F1#Sh-?BI|45mU%3V{{(TQBnEknkMF+hnhBav$Yxfl z)_VS~Ie4w|)Mas>!@y8IKbZI46<5n&MmGr~rSZdl!eKwbuwSE+0etnY346$rYy>~W zefT`1(XVk?5|yx<<28*)&zQ@@*i9K z_s`Ye=YXGf+(Uu!v%QBiNU%wb$^AwCJFijenWZ?>}}#Q_%&f^v^#OF6PQ*;zsR8guV89ZKy4{xa6v|e!sSB zg^;>v<`so**>sglf!589ph;EwSBr`1*n!=0NTKdkh$+O`Z-$dj@1v7_o{MkxtA*-5 ziWHjWrco{W-&)wHj&1?<*TN~NtuIo%7678XBZO2Imu@`8RjR?v)!i4ZEzuCujku&D zFxEjth&V!oWUBfeHf!AqJZ%VytLoLQ%;Y$6{W+6DVUDUy8Z8k+zuilNz@PH_O6AM_ zV6FqEsZ|J{is4MO28wfMzK4VgC`NT)_R$Ur0LCU8-IZ-OBO#(*C>sIX>czH9I0%Z`9_}p03rTqGbo*Kj-xYB^W)7;&G zS;EOIkk{@C=Ru1U#fnscV{ntlx+o!wie#>$qc<;YOGj6$P?#F>m^)}sjb3+REvV*H zofTv+qHqH08XJv_44ljoO=?2w!N_HnSem`uP&n45Ty8bcp*SofwebF)^Tzz zzJi41uYu~tPF}D8X;p9=ce4}Zq8C8{#%jlX5ZzF&k*!yAX5ANTT}cnzF0nsWaJDri zpPnVzES54JMznaXm;?_m2G|~F*AhN_>_5a)CPVM8jTfHTEXhk-L38(xN4N~Y=JD-= zcu~xX+2L9O9e7eqtPN{OuH%JxT>D-^6rn4^{8_ee$lL6+WP@$olMPERC!1KGrAPB+ z-K(2LLxYGguLoG8E0;0ShX}_y&?3zzcfH4eZS@v{Q%$NTNkcF~{yiG#fn(2f4U%|> z-^m<<7=m+glB|9ZBvVuOGZ5~ELN<+1_K8U)6%G_)!w~d8r`?tQ?M}QxCXXykuo56T zYYFu=sg6b}Hj0Fs)-rz_mTx%yc%~q8e))FkCaQXZ&&A>pzT(e{QVO_1s{rd*XXP^9<(3yPG19 zq5j8wY32hx!xQ)YFMn^miyGLjv2)WgEw>_!=WWZzWW(v(!!ze?KkM9bJ$A9~NapwC zJtuWGdK>7I;Eae5mdtruLj7k~(aE9u-WpJ1frUIFkK(*<0Y4LZTp`oRqr zUPvJScxjmFZ`Q}skHlc6QM_97N_MdqyksWbGU3%bW7`{Vy=~u=p$&BS`I%p;H^umM zHq9HRL|jTic&+FM?P|fDNU3bO{K%{Yv=_XHsjMj55lh%s=v})D`EqC%)lcswDro*e zXv6UzPFp#qB-h=zSN(==R;Z~-L@rbZ&4(VxJg)G$t#4pTygW?Ok9zJEJP^e15d8ZX zWr(dlJm9>~Hxc&Nm(MF8I*IW#wKf>_S=G|o#SOhrefQ&DY|UAHx>>Spdg(&tLicj8 zc}9OtD-^udgW1-c$t9*&lv?NH4o<5IFw?8c_n9+s7L#@v8PmU7dJCYjzR~*Z1}8yA zi{nx8y64G0d+v*mRaZ8J*^jz60u1LR;i5pu;uyxXub(9@HoF(!zxm{04INIk4}|=q zA*m$diJy(P`HOSE&|aHiR)a9Yjy{}9E)-Z493HMh-L)@yR!6Kh!Poy;d_I)M)5+vr zV1Fl)VS9;C-Tgh+EzTr7)W3HOW{Vv*dGe47X!%|t8mGwAgb#1PeR-?(Y%}kC5V{ z)E`6ZY0hxpeJAf2q7tb;JAQW^3BKkb=sNDP$AkT+C%m&izS~TcaSi)GT9fx} ziyjOrq=9H&eD0U?L1VUWsx0x}8Gf&UDc*voT4BHTJ?q+(kOiI71M$3%O(y z#Wu6JD&~QS1(l=Yncsq6)e~#N$-pxJ9wX5BYXC~fbjciGe`uF6BWFmRXdaRQw0znD z%;EoP9Kw0K+ZP*J1NM*(>cmG7YQX_N+(@EV2;6DMIB>Nsg%;l1@?BTHLDAv+QlRhw zdX7!*y#peA&uU<~-Lh&0O~|!QvvUe*x#1*WAMs$19ssBSbddGt3mETxy(4Lc*akfD z65I)_D14ZAhnmNVf9;yyb?zt-DSeGW>)E~7na>g!U*}T~;+?TsG?#@~i&lxX_But~lFW2NLkZFN+5zf9l>aHPz3gG+d38J}U_jQt<152V1KFF;ym9IvNV-I@7W+i4k zhSzRAW+Y6N#CY*~ z`oJXCrlb(L;oNDpN8F~$38I(0C+Y6;n6f=RCM$grYNiPD+nOMzq>K5vd9+J$cvzC3 zvwR=A)V5MJs(!XI3a(48eBEeOsC-u1t=M)cdeD-ZA!J?cuM8 zoDK4(1_1Kt&7icKZ=UGz+aB;=;#bG-G)I9J7O?|rl~4+xFFp>$MQ*E#x6?y830&G@ zr4Gbe>fyAB7lA?(82x#5wrQgveU$=rs`?82euY54a$P=A26do_!udn(k+GC^E+nS_ zw=_WJFU&#fA_UzhUp<*jQT6vODk+c>ASab%{Ze7Rrb@jrCg5n-D= z1e(a?PUfIQA;ht9;5fj6u~B8Eip-2!;Bv=V`C;~42 zoTQkw8l{}%E~c+SG6!gN!S7AGCV>u!tDz}udx77}I0_eLjY3nxG-Qo0!QbVu{+ zyLHCGgo6&rQtImZ$`&9*I;^TW&y75|*(_(eNPQo)Joj_jJ6gq!gMo`+*;|$Sbjyy# zE~%WN)J{7ujfw5NBU&RuUk9KmF$6l>)P1bgLMgF;&EQ3Xw{W6gDx~PHwfSEytx9c;W_1|LcE_ruVj^*s)yHUe7jlG!o!ugll3c*e6m|0Q z>9S}Bhff}2F0of0MhBVrGYq;^41{&FiVno(CH?_-rDAN9ANPJ;!CEnx05>rbz4nIN{bjlIfw=szBqYFFBq zEB~NYdElp@dFM%oHFDaiwbnNOJYw1F1~1L4=Fd9$>}`!TDYy#MZOlpyvnHDS?lu_v znmTT7(FH-kjCWhzi;xFl?{V|{NeuHr#&(laj4hlk6Iwc)Ehz_|Y(SamFs5mY!MxPR zY3~6K3O5C6YE5!dyf}k+0RNw!(9-=do(kK8o6s3VlC*TLXz7&d4xgRJjbzNfrdfEx zXpeE1emXn_EY7yABsvPrnWz{W>mMY za4x#ox^=TnKy6B2>G}9>x(Oi^?AhySCo4c&icoy`;t*X#9&ZaCJ)YW}uoDC`jbJ@s zzXU#mar7UyTUZxgK2bGLvjMo9u>g9YVd_$i|B$V@=8GQzN;Xw z$wy*Ha2j?`>Ol4hZ&P)&=kyaY?Dg1LeN+Z%Tjec05D0O%oAD1EaW;(O4WN$)R25Z`{82cMfk@ud?h3MC%CDNcXoFD>yKEA7dJ|t97$-gEjy7N z;3QYHU`BxboX*>v!K>JL4bk5Ek`g)Lq2gmk!W|U(Nn`mgXdh zQ%Duf9X$ni=Xx4XJK7G9>cddE<_BvuonRYs!Nvj#>xyn&uC&y2TTc$olvmoJ5Iw+lq`EPe7@Ic$c2TT(X=w(X^h3&XI$KP z&O6hv%=QcB)Nnn0i|r6r-=NsOW`v``F9&Z8Cd|2R)yz{vyOpQK30^Uyd z0~#7&2>tCO6CQIxslh#$qdVW?*_Fo{mSE0(VI<{>3c^^S|RzzggZobeeao41bFTKL}Rjo6(x^ z10Wh2J#~kxjJ8f!CbQAg?7NxWgPY`yCI7NfsX_1(AGb~VTb+0ml%R=tzyjPmHj>88 z6MbLw_WgyLlW*mc6(c#i+dY?;5y7Wx)r-TjEZ5&YybEfJH7 zp2H6ofpX=jLCX!B1m0h!-{_!xGD~7LfH=7&)c;;i{cNc_JHR$V7XSRHQ%PQe#iQ@b z%IRCmI=l{+eOj5+Od5AI%&u6dWb6G+7mW1?37xeKP_qp37pka>N=vq$a;oBy!!b(v zIck=c|3u3EWv~uUn=aQ9EXbmP9+|^r)Z*Q&u4s%qdg2{1id5^vw@nd-w_Ot`x%m?8 zKr0D+`^(OHTBAbZuCYUvwa_p0@0-jj=)(YD+sFRntw;U$E3f5BM+Hq3#N5h?P^&qD zFO>|&tg?%5;qw;EM)_>emZg`8atrC(uQBPGeNmyM?&k9|Mg#;=JK3dz1#E$Rd6Kh> z@=t4t#+g@07uF87DWL2ge(tEE*`EWk;#k6|BHgmBYDs>XJe zhd>#}>H{Q`qCnOh2*n9MYp;a}9vDP&S3E#UdLrXb(4?!9wysXL=Z-CCi?%5m@1{re z>}>;h?r0EuV=WC&FSn_y0m#T}HF`3cJB)LUQ9;qGc!%ZUqklF(H6AC?x!t2N>7Rk| zyr=)*${}dn?wTse>=H|D`LOJh`q`?g&zd{J{k%>QLb80Je9A9UMai|^HmZM0jxZRq z)Vg3ieiAKLa?}bi)_jH-yBD8P6rb7@*$-S*U{{?jQnUVT31NXD56pKUEeUt%In3=i zxE5D^rXJ!3-+c}jqWKjnYH z(fL)I%HUdRTWU8%IZ@`IQ1|z&3?#?-ojdv8bz|?xZHRPfxpCCF!^?vZE3J>h0$xIh z$X_KUtNXdCf~wDr@>z$@LGN}53U3ARbASgyT0x$J(t!)Usx|DkY;hZ<2MmoQeKGh! zr814%p2t!O11GH&v10}~*?=srzOx8HlMtVyZzKX!a;DFYWubafNfD{Q@j{XhGOp`+ z5&hhEx?s~Bs32O@X-=dH&!;*lAPR9p3@Gl2xRDr$RJ71ytt6_r)6i%-ktI|hD9MYX zD)~w7>KGt>tGi+;S5l#VT78vRsRUvut9LPztAhArV)>GIBz@&zx|G6Q=7PkY2+&oC ze;TjcZEZiu;xF>o*C#z7qLKrMg}{>g-X0pH^k}CO#hqUPcyw+OKs`aB)G7oeT$6Uo z9474_s`<@r{SPb`o6kqLw97t9!u9A}+`z+#trN zDD41|{~S&7AWnqOTZz)uHw8i^nbOgd3(5_u)WY^!B22qUdR9dCX?{p@OH3v-O{&MZ zO#*VNx=O{Gsw@4y*DcqmQIW^y>1K`sS zBkJ#u13&q3`VP$d+{|6Fo&dXa*~Z_ti&W~=3z3{|SzCS^*+G^EC9ygSJ2@HihQAovwo|A&U4dx2nrwxqKn!K#yRg;|yoP9GmRi?jxw%i!8h9>JMDEkG#= z?n#m^xQos>q47>Np(VZo4?}mBVfp0(yxaUv0Iwej!UzzL3^P$Fc1}26d`cs)z*G90^o?7SCHiJxLvU6Kcwu{SN)vVZppb1E42+T{$0AUr zm%$wBWpe_>sHx}KfcRnOmGDC*Ve@nbuMpr>fc!`<>o7JP_G1rUi$EI!u{+Pglg!+W zyy{MHR`Mdp_c#Y#-C#{SMwVkuLTiwi(-Ab=KO3kT=1kNjxR1BD@Ae=5rhECGVFZm7 zpRx5s8o`Tko~9oRL4V99M0F;h10Z+h=m5WJjO$-+Od1}1pyRG+1z9{XXTUE$I;-I{ z@|&v{O=I{EDt6}DlO!{fZ}dj=EzDCd??#$Nm^sK);!1)7gB}&`)gR+T&zZ$Y0_~zD z3i$Dkm&B-@t*Aq&R=5-7=h8-qe{0CTd9Hs~{m8rz6SabRnxHxQ*N&EJAhYNdr>|f3 zIQWN%AHFNpx4#NGh6V<8#N6=7yfrRF&g~*OKB@73c3~bh;Pm3dFqW|IQ6u3G$MS zHsWW;rLnLto3FlfP(r`5KZh36tbIOx?!X;6nXCF~XY?tSwBuNxBleo97tj{9#iz_IF5f5(Mqa)t66ger~n; z_tov;mYdaBkOabOm{_1v4$yRpaRev->G!){;xFb{ToNjUs^FLBNQPfOG?_C$6nE*D z)V#!_sPos3#up#&1Xz!611x(0i5WTXDezABbMJZn>E`j`6mvJrKh6Zd+Um#-%QQ8y z9j#56IkKt#;*C$y9{(H(yyAbM^{bOVDd5&nWmr)Q&ps%t_3 z#lpZ7q3f7^6pJEHZ*<-ixFP-`xTr5<^MNR@U7k1tH$@)P*mdStfDH*o&4p2HpB|&R zc%Mg|d1Q{*_}cY!7VgO-%Lio^=6^7};9%CbrAC;5IrbaH6AZFHK1^o*9z}pBp^B^x zw?-!wPtRVFXgPha!84e(4h&qHZq3gvBwz@r|MGaqorpV|%`lJ4wH|}3ek8jX3w$1M zr==jwfD^Le9)fOgkqTy4s_wu>0?K#j4uFU3YeXgP2SrZJbO!{p0fxrY_gFWOj)zv; z%ikZ=pBTZv*^^_P%7=;Q+cdUt&lZf|A_zy2jN_+pMPf4NaZbo=qVXg&QgsS}c8RU9N)Y-Gl6|PjSy)?x2>isZXPD*Rw=YFe#;OoxQ7X;Rx z_Mv$8U4M2hvI>)lPFlSe8oCyI-!;B0q)}vb_056QRHqWJia#D)3c&X)dOw^N;$hRU z(MjxkC!X$IJROM{+_#H=J|x&oZ_-0Bny=uDh`H;j8T`2J0)c;YY@UYMjt5)a1)2h2 z!0ksjJ$BqpR|*;4`PxbI4Ql>}VLx(4t@lo++m1hS;cmghCrIx$&u*?5elqRRI46ml zE?3`0V%sPB=&}jL@{~vL%}O=RvZ=LM#_v`6kmSQTM-qH@%Rfbng1OT74vNfnVuWIr z?9exea2Q%`>_E4%G$i}G8!N_i*Rd<=yRosETybh@>|pvLcdE80Sw&Q=`vSB$WUh6< zvOZ#Q=H<0i*1N6SyY^bkrDFitpy&Zrn>s)Uo41ArvpU40_YVGiWxaT^FYBCLuQX$V zBA3odDBIj7?c2G~`ax*sdJHQLnx&it!d_1ry9Rj`Ui6HRE{|J_DGIO>g z`gjC)#L+ckD1Su8oRC4t-N1C2PuB(!PwD(Y%B&H0LebclYqZ9aL!XyxuB{~@@^zo3 zY%MM8@9Y?-fEU831d-F7^{ z|9jk>uIsT5oQYx*B!jy7_gn$CE^7^+3#49oQL4kb#EJn4$smH$bk7}XSGUb6#`L!) zt>x)yoXAh=6-$*3aIWXk4(LWYOT}u>nT%>-O~khE zRz)YzEq2L!xDyj&YL!FosYNLOS){8clu!}}1GHmErBp7fMvvzJJ3@zIX~16kgRa=k z&z>tS6mua-)<0o8bfz_l;&lq7Abv&BpePVzXLGcbl!=|u#3_}EC0~T*!CHT%*C=^K zC_5T270+E}cKy_xaP86dDOHn-c}nNax(D&A?&Kq%-Uz?nn0@lH85YZp%vAzX-wrvE zkQq+_iZi5I;YEu219UEmS z`|sz)q$y*=RV%$J2Y&ksuLsH>t0FnDZz==Xqb)SRfk<@eB9bt5E53nqELqRw!FDAn zm6CEVj>DhgK+2fFd3!-bI}4Z$%%Io~VZUfXC6vW+BUDSg0I95vHJ_8(G$jIMG12Fl zm4#xC?ZJ~K{vIvaT)k0XcE|>XiM$nqo<0__v$C)sz(FcICf1!Q(>T1C?ny5MrAIlD zbQd~fJd`n@wM5b)+buV^EZwOv1etdl(st8YP)QOkqNXcpoc!>Zb~&RqnLkhqF*fr8 zhFlE(WTjYY(KU=VPjl3YObs3;_cgsZ6+Xzo10`LugeU5ZzW(>Sd-`+kGg>4ou@Hu?~`_3Tkt z>rnK{P2dEZ_bla?KKeJ6VOtvfQP@IbSC;ZGb++fWH*N3H1>HihyY+%ZYr2433Rcym zJXB;5wlOn|N5Yk&im&mISYa1=p#?`v1EB-~-lf5pE)pO{rOEn9z2l(*)| zVP~CJ#Dsqf88ga2kYLsLKDq!w-|~=^QdkJ$O!-|Pu2cggQ*WH7W$p?(6#(|iSoQek z>}NX6n>8oRGKVASW~tto;O}*3+`&Hza3wBWa--Q4ed7y!Fu{Rfdw zTM&bU#|%V05414SdBC0K!~=)~Aa~F0w#fiZ?ii3GKY%Sxak3cDMxeLe4jv{^?e@k` zK0W5Pud8M5bkBL9TYFlV;2ZRTNUnkWv;oC~p^HJ0DVViQe94Z@w@h(Ag>0{ANn{#D zty@LU-9Hu^PTmz!+0mSB9C{`J1pB_%_|*usS!UOqYz2C|7oJLThWXmo58&=$K4Hx5 zkiUHK!R#?d7W{u>7M%W%k;G-c6Yl@DmpK1#>?O|sf7wgEJ?8(Fz2xiZsLWS|<>f)y zxyHcO=Qy0w|lXF!) z^Utsm>s`{7bFU-1#PX{>>VDvIV<}$R!F%@o`E#S+e@}0y^Sfl~_adhw#}hJ_Ucwo^ zy14HX9JnJ<`#R9@?Zt6-OV54>OWIMn;nuAPbZ7AuM=uO}Cg}xoN7tr8AbrAs7;2`2 z2idy;EeRENfvPv+C@}hV;DS3+HFUJd&Eeh))!u1mwH(Q-hsUF$vz#aD@!vxwB$@?(F4+BP56Z9oo$jzX+#rrpz)2Ih8$v$LD zN~vh~1R#NkGe$Cd%J=dz+314BnB0JQ&?qBunTSy}#6cuCB?4NF6GKZpl3P>)cM5t* zn}{71NRr8J#J(mdZS;^53LKf(+@>IUjYq^0xlPI)pCB^p?OtuEa_uQ)Qg7ZPoT$1` zx|a$q^6zQri$mk4m6TQDd8~&*#pJaP9VHAzij~r!veevt^vgZ^YlU z2|)E7giWN4bGGPQ^SMUs6ori41=$44t1^h+A?aDijl_zHV&zY|5=|u~TRh&vnzV0& zAbI9>IZQ!RLkZurxzOTk?$BQ04>bi+H8gip4{Rv)Qi?b|eO3w*^k@f>*~acB#!!}J zsRdlMYKbfEWAx5-OaZJ^SJx!7N>1q|zC1eC_L0>m3|GcPNFi0XYg|RrT_0HVk;E)j zY;=JrJ2lS;X23vD28nXD8IgSDy^%|M6fJDLTf2R4P(-^kO37xe*eY>-$6%-w8_)nZ z)SMcIsmbEhWC+81;_Te#+K-!KygJ`T5tz5JwO_WLC%8Vqg8f=GzV~S2$wD7{~`IPN*N@$Y}Vbxck49bF6#Uzi$hFd*)^6DS|KIFs* z>n=TdYap;Gamj}5V}FL9KHR@{02_gCbNAbI+J^cg`4#HNpI(b?e@F|gd~Rx9cVGW| zy6L`s-GT#l)VeZMGrZ=*!V=9(yYiP-I5?`ki0XWK7KYw=@0NBADVS$X)9;8gUoZt+ixM9OXIX{}k-)}7(r94a|ZhxdRNx7F^acwPJTh%Qtb&`Z9X*5&E>w5%>4W1fFW_s>^}&aPz7g^& zn&4!17Mxm#ZtV_x`0E?^qwuOPIv~v@&QX7z3AivDSz}>=xs3Yp=yxy>7r1NW#M8MX z@Q0Pe^w&I#L!D`WKl}&u13Ud`*@k&N{03#Y)7kc8WMxD^)%C%Uu)cGejnaR}URFN@ zf4S+1w)su%WjN=ZefXt@Pq5Ecmc>~kR8cibe^dO`@4#IPN1Hb%(*-lrkIbK+@}I%1 zMl=TU=P@G*iS}^UMCw^r9Vbti9=zzIL5jZiJi~m5p+wTbcrt5z;yL#y+ghf6s3R)o>?qkr*JMnbAT^ddnZW_o2 z`hT^n40uTMdpjg_^VX!zd$52*nzQrZV5^mm{$No(jd5L%L)Fp?ZP*{HP0(VZvQYz` zWJxo#*qX5k1x7h0+S`}`clS0p{UQG14a6Pz8Sg=BP}NqbVLFDmhdAP;d$H`~7JdD% z9y*pA?roP)^_&miYH(>+fU+`PJUG^Cf;Afa(AK02CQ*#mnj!k+a=Vke_amy7R!+SL z|HRlWvQf;-nYz<3;cxV zv9yt-X;{tS>d-iD5c+rX#M`(A?GOpDu*lGsM0m#&dtw+avB0r{D>EbfUEYKxGnd;5^O1 z227ULZ9H@@WS~H}RI^!|?9y6tYB0DWKl)z8%u>UwHJf%m3lK>%Xz|0VMJ#u3Xp9|rwLtph|E5*JomYPf4c3p#}nnFSP4lc46E)GyQ&N1`s@vWP9b7wNaZ z)9+4buz(OD7`{QTg(O^dB_D9LYgU14eil2MmE`*t4aK?!l3A3Hyu{RkyI#uV(R5*V zY&2r7E-xW!*NwZXw(y*0B>m|JH8tDMjljYy=u@Lw3Hr0vK<4;_v;v;^Gv=*2uz-Y} zUdQZR2@AS9Ql+`wib*VD2l&R<%j)1IiT^ARw`AVU<5MD$)&cwsUVdEPx`&mEgiPMJuq8Ja!*F z(L=ntLx(#N*MnE{3!r7YCdTeK6XFtAvl;rU%;`k_?}fPwZ3NgVP+2NDCI)rM8EzjFD$Xf@3K4-=t!tam8+rw_~HdkLqZir6{(EX;l{}o z&?=}MTfp>969Z=+JV2Cvz_UWyWfyJ{o8ec{$$&@#Npc0m)!Bp_33SSUU3bI|PxXWE zowo-`mHY`ccZzPD+%=j0RlAEgRtUWN@aE~9`f%~*E$PeMV9CajE>#J{lJE;?P!KDj z@GJ|q^rQo#=8l{IKP+E4svgK1yDN?Z(0tMb}pS4|8`IH-+GF&U^k1xRRnTBa@#4arrrgvc)1T!eA$|+WsXsc zAvqZYL&c&v>7cfR*gULH5RUSP3*K3r+orxL>Gi(sL5Bo+JLCQdS$%zH$N{X_3?cDK zW{gyza!{2Co8)|D@?0&{L*yt##MGwbUKY~6@2vMphHve7*IGW`X8)8bGKM%|4lS%q zi4}{g=zqL>BPnVxxynHVbZZYNldEP!ft)HuJG)Z}L9F1aCBCvvW5w3Fv)5}2*((TJ zOTyiLq?=Tu)WPz=25gPE3h|-tPHvKj!nrA2sTHbR{J`dvPZ>>L;Btg~?xI{t>{hnL zEk==de;$Ope_W|9B5AOfc)>L!cfhL*lp;5qoxoKVF0$J_=EMx+)fKZ92{}I*l6Le= zHVatLI8h-}?E+CyVV+tDuo!%Z&$u%fEVyO$SB$B=tWhFw;;3mpgXv2t5*a+Kjn8G)W<44`QX`n zB$S91F8R0!-^=}nCRFaG)#BSqF2_S_rby5 zk^cMyd+e$9^Tz^!0R=le4Zs)GKO1Of(ifAvJIaeye!B&;wdaG=o6LU1hY9+SVs zYrt{S}&=U>b8OsuQ;6=v~N5!7(aZpUzHv<8i>#O zq&BNx=+OJUK@hgOYLPu}P0EtNuVg`=U$tD<*%t9@pel0tv-T(%QiVtURT+IeqD`UZ zetG!-ZrZTT6RVGCwmhqO`um@E7aw20a@s$Q&Av50+;j_V@I&Y>lG7WF)hFMV@idT_ z^-IN}0K3jJ&pk_p1<)-`Lw5XjSr+qp*~((}&ojTeo84HrrEfGA7jPsjf#%LeC0wY! zQVzd}sx04#&G^v|^SXS{vc*$?7ZreY3{P(WgkJB@0`Q*KrcfKqtLL7u%;JGMZ#SBT zf3@S;_~Emd5y!&=xWg~bIm62_wj*ARDQ6n+DEe@KzEM@1hG}e&i4AIQtF(RqmTbBi z4k~wHiTI5SRMJH%GttJYA@PQr_rtZ&2KVI=c5IUXF%GIVwnkwukYMQ0umLBN(Bcb7 zG(BAMBG!0JG(W37$XI6)6dNW zGF^w4R5GMLsBK-Ru>~+I@T=|X+pzpJbU{UG<9uoMrFr1#Nn~hk`@eX5^Qa{A`0f9h zA_Z66a?1qQ%1p;StrW%56t&z+Q^c_n6}85t(Ub`gwWe~ZG)*&8+)~T|ElnAr#hRJM zAjKdvtC>j=wHZ+Z;r@N*InO!2-yhFk-#>om)T!e+8L0PtzdzUex?b06xevzD=!l8b zytDj3{-snwMgs_ZVpifsRjiJE#kbc zV9dDatB<-WYcfy$8d3#xHx~gn}H0^wqU# z^7u53)7A2YqqJ3ZEDlKC3FpZ9U|+HpvNkAzxW&U+s%mAz{$btp`x6rim4nLc4!%_x zyKqIPLZDa*dCEcKNqNvv57nANbe~*gfdFA4Oyz$Cx~#XYZDJCl52X#0Q?F=j8~vR? ze%4b$7OgXZ2}h}Ye}Tk|)7rs*(z^PnfS9-NUAG2Qwg!F9vxHQ%?8KVm?)h7!1Ja6h;$p+czOZ4pJft5#g%7_roKau!!NWNTlf2lj#ABtP%$i?z%y{``Y8J0Ol zx!5aPn}#UjOwEnzo4Jm`dvl9}2-YQQa{nO`Q%S~!n zw}n)~MGoNK5k4Cynv;4dWVq9cF|+8cJ2cs)9E2o)M+;>$(_{!*Rg%-!Jwx}|GQ>s1 zqDWcm(&Ug41kKPV*kmP5HlrFN2a}nm$ z$_DxlRjjJOSUb^oNZ7-95VmTrWBTxs$}(Yfp>j_Ef2Hc*W+q-*IGL1>5Ut!8sjh(1 zhrd7U%R}T1@44sPZ!9dDR9O<@K{YJDe+@4nLpEV-5ECeok^3&iC=jrrgsh1@lU!&p z(Eu_!*#G50g_zVy^Q@^p4Ia0k~r= z^GmH-W+1V{*gjG)F% zM>M_B@nVTvOk(QPwi`r!sIhM9{+7rl*bXL7QG4r+;*aQP**x}s1>1&^7=_}sy@_nN zS5rL>_7OG(s#96uMLE~8MFcf{ZSRyU5V!2a?Q=IGs3Ae*(|?@gO*)9+9cG!4+;N^p z4{&XuC5SkMqwx@oo$5gzR18?O;CGiEeeqq=gABH@cb0?U2xKp8a zjZ_Wfe+!IrU{pg_{c^DX#gFBAW{za-UsJZn(El^)+zQfDcLTcuT(Bk#TMh=go0f)1 zKuAOJcb5U?!Rk)O3(jvDQF>LAyL7C-gg}3`5OPnPcdnUoO;$ND`09QZNqVDFDwZo=O zl=fY+i*%z%*z2(%ztHyqgA}_w!gXt(e|>hJ%w?S#YY832oZWXig=X;l!r_S0lm4@@ z!o00+!Jiu@Uq3&V5Vc@}9gRe^JwCS6#K=9GL)JNYV*eJQ5Z_}Ioh6CmJ;*G-vw3i( zF6P2LOMAOW;ac$G@ZZ~~@-B$d$?NIFsjw8-v7x@(;jMHtD}rU^Rdw|{+1ZPWzRYJn zmM`jdp0UMCHCZ~`;PqX^Whq%Q*>-aCQHg}nvGk|O$BX{cS?jV+sG;R>;KzH}6s=pv zsxGGdZ$e&m5eHHf-Gu+!xzqIs>bHMRyn@{*_2>`90*KZebYSma`U4rn@+#6>*@rBh>54+CKSzc*~c)M?pY zqf}bis`;l^I7L3}itj1;<3O3Pu{`N>nUUU(&>vq`{`^Oop2=Td?^Dq0mp-L{607q` z)bN1bx-@`$i2AfhDO!FWR`I~aE`8R0oH%BM>C{FB(<4qH)b!LNFnf|BsM!68*NVz+F@mu2zs7!Yft@^F^(v|zehNIibCK1q zo6)e}ba%M?coFW}UY1X6I{hR(6bUH8sqRNnD1UCze4YKZ!=mPxSKCv1Dsl{REGlmN zgF)5P=DfwJo;ruVnQjBMrsg_g(gX0PnHm-DA?`OrU6@J@z*_pH24I@E&5lygZb@Z+ zc2p0W(x+6I4z|yjy3f@kW8BlbJ{y#-@G#A0&gH+Cd2qEiYx6J+F{$Z;MQJ~p7MM-w z=beoa6UG)iMtk2j?sd=+kJ88NkhR;*o2J#ai~F-9;T~pcViMR)Ol5feuOH$67j(JD z|Jk1Hb@~6)-+FrfPj+e^|9|b&{(H^;qn+CB7Sqv2jYHT^5vQKGT7Swwwp&xS!Oy?c z`z7G z{jVV$cZeQxbM@TsTfESxRJLGNZkg_az0rT`TXoYdOE9qj#25LBf@?M z-2Y*(b{sC7W*EG(PpcPY3J%j79N6bmtA}*7XP*C!ZDl)T{)18EoCKoh6p2M?|ti)gUd8M68qtQ_r4v5BMURFDRm zX2)^wl|`Gg8!8ndineOGv9VEnctFb$b~}8aQ!wGt(-F()eFj}!&vA?e+02EjFqN=) zm=k+uWH47ch4WQ(_A}q{!-1@gQ9%TCN$~2#n{B(;dBR!m{-qU5pv;oU6N5$}TUo<^ zvUyv6WkLusOfB*Y6GyuHr{PLnLi+0d{dvC6z7vM5MagA@ZCOfk;)*=6o-@t>eyKUn z9?82KoRRBAEi+xJE|t$*p)Ti>pHH*jlR00NIjIzqJyTiEM94=hXPLu}oGyj4rKNJI ze^4&Xq zt~d%QJ#%}$w)>8~*gP%VLMml$H1r5R3A@5-HY&MFXsY0OnRJ>w05ms9HKQ8t*XBU^ zPzVQFg-&=D*QdWPV@@hJ9CC4$!q)dJ9yDW&$3rSQ8!s&-gQVoBTqp#Gj=oZ|viBWt zCJu@vfkAvfuUKU+)rToSZH>KDRpeS)g0+>5jT;7^D&igkffIo&x%K zQLzphk%qGs9j_80W$7BkQJ^g}VK2 zgsGgQ^lh^&ne)Dl8R0C@>m+?<;2$%Y2dL@8oWz>`sBmTRY7O0tH26-W;*8Sj9}t}A z`iqleOTATHYWi>s)`*!%svPL&5GMPDBv4jb6LQe>s7{fIB_0O}1>_ZFCuEc0q+l%e z53&U0X-+=}ghE9sC2f$!N$&P=<0oGy?U?AT(z1I3TOPIPHv#ciNCE)a{Cu)R5v#Q0 z&m30Gkk_V(OfCl!Ddft*)d8{!lE?J(GG+8C9zt{`rn{Tb5C9XgvujZw>Jax4q>`9j z6BnIla|L9-@8jUCJe>R~s*qpt5?E&H?^38Hx8^sS9g;vi!svwm^> zw1-2tdO}<5l7xrwk!YiCvpBtczCgG*Vq&Xhx0LFX^&roL0DHoC(pDJU|Mc~lVA?pz z?X}$qprZMM^`8lb#l3uaFMRGYXgKNK!J3MxV%)M|NLy}Yk8ZB`!#%AJW+}>Fy$E5M62yUiN5P?K+|5^%{n(Y^TRLq_fWFA1P}CT&D(^w3A^s%2?La0ZH%GG zVGk3Vrdw{^9=G3ZOL!8O5!0Q}h1iSu28f`e!StI(0z_rhCe-YPr1lEF6^m~q6f>%7HfQLKakWA6`YO3pP_t<6< zQxo5NQ~w*Q9Vv%k6NK(-UZDn7QwJHQDS!0+yznYy#~3z{cJOyf)mFGOPE8M$fgbG$ zJHt%}7MIY<3Ac%$V=>&WVec?E0P|z8cDsk&4i?ipDsC8P^ba?s1i^{d-cu1x0)G?K zuW)dtJ9EML3h()&7jf5X%ToW7EWzS8q!7U?o?(ryh zw07Eq7MPB2n{N77Tki`9ymsQOa8HR9M(u1b&ENhNl1mFUDFY3v7+T()%`ic-o0WAL z0cjJLvorOT2DPjuCz-pOc6s-qx&7)}*N)9siDH%e2f6CtV~xc;su;U(q!xLd7HEhz z)Ptkl{xkdp0O~P3)onXGUStNsD~R3qy6YNTBVOd3AFK1i{zZkCKId6CVJIe6+u)|? zCNAKioPN@KvuRJQy@;V_G<_^Tq4HFxU&z6XNDrX2*1Cr3sox<~x@jYS2JU+rIIo+I zJI-q2B16~9Tk6nv0Hz$!}OOazii(^-Y`E8w)@lbT? z3pjv)#kf0_{C9mhN`X90K1SK20Z@Xi+ zi(uj{Efy$Hb%)TltKug$R)J#AY;s#SK3GyLKK#z2g1XuOo5{HL;#`o&*oh3gK?f2EAHIZtlZAk@!l99FKS&-^a2 zR7h52O;7+JYWv7nM)+aFZ1&ebIWj!E<Thhk$mpb4Qjad2?qSg=rm?{O%L znK{gXCZt*9#UTXf$yVyHA^OfeHI>e{&jC_d#izsiTi2k$;b=K@N85?Xkrj6J@T^9m zZCfRy+4#?7fXz^n=TXC1Q1kZg83n;f5WBHQ&u9f`l#*fml90QGhir7Ap`|&BNB@zgl0 z?&2}>gp4Um9D*==q#y%_FU*BnxkXMP1ByN@_#6$oYjQchlc_izF5K`AS!LhdE0C}B z*Yx(>Ug_ry0xdFFIRgo&p}pRmkwJeD6coi=ZxzKAPlFBH%S(7RsH~8W%&3;Q(3(ob zLwF|MOY1+BC5Ki8kVGz9Vgm_IaoD1pnXYVk;xXKsXK<0Z%2^9hFxRF+)(%f9eMii) z7akNwm$@I;-Bj0GmCetvs|O)JGJ-sSU*%a}s+SFp9%$a)w{=@U#UGe6>iMajoyn9l zIJ<@{R=2u}cU;5g_c;;NWwf=Q7fd%89`UR``YpYR%S!2Dx0V7E_!9^Zppr3ZP z5*dvPaT$@uhO=t*VPZ5PD7H^uAAo!Wn%K+>G=H?#Zs+@9fTLe8ZW1GaKm(#E-Erxl zP;@E{%O-{9j6LhEdwR>c{IHo8vaH3M=$}-VVdp>CnoJR;_l92Fj}ln<0pnKEuc&fx z@AtY+1NTd{P`K4W)F}MJgV0M!jq|)v1Dth%)~>Wet~#J$MenXP1LtK2Z@1o6(M;f7 z^0#t2?f`p@*0MX+rvcaJBi$uD*f>{heBnH~Vr$6J&C)IRF+sYl6WQFPzMJkZPI{q# z@&EDFy&n~4&Miz_Ka}eJHP!srh~SgE{Wa`VFD!S{@8_K|@k)y^{pOO^K|gPyUV8-{NfZ@##+THhe)ZQoWnx4cotC6q#RPn}`s>+I1G`_SF19Yn zi}PpR{rLI>2pOI5@~Om+l*C%EoI3Sff}JjLiA4US5j)9p=dl%8P)T@0r}<#`di=!O zp3|z^YdzfqQ+~2_qTMGOy-agmvAka*X%*TAk>b>KbgIurVk#e7x?GKtCrX|_M|O3t z$QkjK=TaAh`TVR5i$^_Mh|0X0o{Y=IW%j;;dG^JV58g6c#PJ1{$8#q}E|XlF#Dm+YId@z_ppHTTpTjFo{u24Qs& zdkBjlFik15pe?%u?tII+tTg)r z=sSm@JGZv~lvf^Kd~gLxgvriE;Up0aD$dq&AMBCOSIkS7qqfCSkRTWC>O56z2OiM@ zSmWj2;iy-zy&4``w*p*jG=f}VVJOt;6aU(qzK&=-Q}@{Wr`PCj%?&Hf3F?jY-ddku zYOTM#aP~~In{O|ss`muym98g|W{NU_n*@MBTtrEU)Zl7!*!0&Q0x+A2YHuvyL8%65 za|fUSJD+3WtIEX-tnhZ!yQO2;?oRvj1~}u_!JC@wI}oQHGp_EvtL}9I@0V(9D7Du#?9FH1R&H!>G9aF01Gf%`MXCu z>TSu>3evT`$eh=9{OlwuVo62KnaMy+OJifhg#|JRdtffUn8y(*f<2)Ysqd(|wmVMV zZBqdKJuOdhjv4o~e~t7+&kkaguUY9EeIp+P|9-0bVFhbKB`L+v<_YH^xka&=W?4eKWYv;<m`SyYg`nU z;I3o~I(j*a?h0nN(owf0^DckYGOkA=Ok_rzDcyDh?keNIF}#<+SrR@VEZy@~1SHUF_)(nxxr6T(B`3(wbndQ&sQd#|PYR%`yu?{D z1b*p$MT{0K1D*O=NT}^UvFRM1a3io3Viqhbi4W0ZcbV@;6e3OKBrkKLkQ}$N5KAsv z@%?1S?PeU!pXE#fXn^Y7My=oHLtpK8d-twA zHjw3s=Q)#*oB%Wr{J^l!n!O)eL-L%e*r>P)^~#`S9)H>wTFM#Tvczn>4I*A-l{u89 zDiuq%#E40GlR=iyacc^v8vd!InDdX{+6-BKwFI!a@KCEvIV@vBaxi05gbVqJozNhU ztbn?7628qN2Qb-{#`a#Eo`o^kXOxhn@Bm?AHX*^k>90h0u zNH?derLm(xS)p|5nOrMo&4jRSE7!y;OmXlqOS-xDkOgH&c0S7hwD0-X$p&NR3KWG3 zMSlmKr!ymU5M*`lS`|vX$-1 z$RTlkmNrY#*|YnKhPNPsikQfnEdfYiwoul;eI{Mer5IR)R;0`n@ZE19r&+N1@4A*b zj3xYVR{=ELGo0Tld3QU3L<3qDDL&*|BI~io{A0! zSjc+Pbt&NG;<^b%q(Ui~)h$yg+A^GgMnlBUcTI(K7tyPWmEB9kz(9Z_PA7WYZ{lV* zywTLS37;$%>_LnzWGr$Pu_t&^hI zW$qHe(NUOa77c!m-<&Bn6BDH+z1=MjFM60H#5lz}1t8ps-JQJuYK)I83J?si#;LRW z6EnCKNr)rajoK`FW$Z(7wcY90*=p==#%nhLga5(u_JkgA6##4=IcQJ~>v3w;xB#>|f>8@RE%O?EXVc&pY5|h#r#{MK8$gphSdmn6 z{eN93vGF?k7A4r7O^p&DC@I#R$vuevTG|tz7(tMmAPt*mkcM^-rlSKW1ERQ{#L5hVW4+Y>*hVl@5}NS8omBq`6ILduBpP^>b5Cyqo*}_bZptD!dTZ2y z-D})2Vh@5g+kqCaOyUtor>uJglanB5V5$e~H(>TZ`t3Kt$3X627o2^8{t*n=G_3Pa zrOwYgXz1p+3^Z8O+EblpH-mFMKp_y!decIYVrFvXl$9Ph1kgc4Rx0+;jZ~hGuAZLp z9X-o)q69~_N`x1OC|U*L!?T;iTP*3@{Ih4j4cj$#Irn%5?*j-~jJ7@i3Pnk$U(vNl zpZ4S5tR7y*;_kw@x&R7hGFHt#p5i#_l7!Qz=V3-&9-Q#IiF=7FXr)ky4V{4x+~Pm% zo^wT8yS|hVn*&C!zx)6&#%0xK_m)?((+Kwd1)w| zE3naXOV|@lXP%t%T}w0GGNGT(VGEZF)P{vKZA}HwSVM%~Y;i+7T>CjsXUfAII08ne z2m0j=f}M#eyBcUKU#E^g@WmndHxC@>s<*mDj#|EZ{o!jj-w!)0=J5{YeGQb8d+Xj% zum(GvF#zH6Qa%yw&i?oQPdBVUZR$j=YY=J_c^B@S4Vp~1-k!*v$Q8+D;k({oOsllk ze-8qJ6Edle;F68q4mzt@Iyi~xYxKnFbbEYZhh_`ddUT&OJ&c(|H?bX8nwH!Gn^|BUFmsH`sl?{_p_tNhi8_OVfgt0nE9i zJ#>9^Gnhuzc{ZjLH{b@KdTSgCD&1?e7p^sUiIO%}S4jyv!wcVEky-9=RPE~5@snP^ z`&a$6@VY!F;rhfDm{zIT?%BGs3qMV4(t5qGP0J8fW`q12$u%?p)n!Bm=(vTa>3OEc zWi@|071pp4zQ?TM9NKE^q_|5hFvkK0`V8cxXR2A4B%j!PZtuP<5kc=z(w#`I`mF0L zxLnLYmn$lX>P@|^=layZ58w!_5ZM=+o;#O(baiuuo%2S&1_ZG{pmLVOcASR)cU6|{ zeU90qWtWtoR)%s;Dxtakq0caKt{X_Leq^LaXtTdYJr^-MyZL#58)|l?ZkRUy1FVt4xrq#rL^ZsSAIxeq#~&Yu8&O`M?W?DorATe;`Z>9jGz zcyENiAQXKL+y@A*qrE`da{Z;Z*53k1xCXJXch%J|Y)Se zluI}A&_aUH*&Sg&c$V%8UqEIadf9l>$!f4IdpyOOh0JMKa5)4w*SeCjV+ou2Y6n68 zY56A?Z@pnVu62IeC3?AUSTnbv)9Pw=WBD{_)4d|q8`e{Aj`+HdcM1EUY_`+>M(@}& zxO31?d6WVYN~+e$vk!!On8Klulpuj>&KZ(2+cG>83f}bg`$7@;oWrNus;dR9me4M!N36^hF{!OA%XA*Anq1^78zK$Jq-1k)@kXQJ!-h!NVh0pn zq~4t{Ww*kl&C>Xo+5PxVT$jczm))qj{RgxzjsK&+!ysvFtPhzR_F*iZFDp!S(3ZBo zw)5AWuKc#yDL-BdnbSyRhTW)cQ5KC%t8=~xSFe)^z0YPQzu?=`RRfm;{D-8x5E+NT zpO+VkC1<)5isS_?RFY6~aTt z+XZpYiabB(38DF+2cmF1`=IUQ;7E;VZKf!Hl5SBUw#HH7%SEWK6~parAIHV6Zb3Wjs*gMV#0qgCXoqc zxPJc&d1f{SpchoB_iTA)N!j2{J4D_{KoW zYpSqYmKOZwstxMh)Y_|1_$u$~w_!YJiVS_WS3*qb{z<8DAo~I($T`c^d158qHLa%Ok zlV{ly@E-D)Al4wH%!B5X1$gjPR{)6HqHIYyQL2L5FEc;eOLI6ARD>_so%XASeJ5p5 zBku%yZV}AVtWk1EkGan%g6vta^vUH?gL=o$xyP zcmN3NmqM7#21O$;{i|SQ8d{lwAVr4lh-fuAI=MfnM(OC5R0F-WhnASb6%vVDB4v{k zp-fJQ)OKaKr$))*j3`Jyw-pC4Ar-TC4xhfb$`K4RA<;&(vZcS>ZGH|9__3^C_HG=ve z{2!QS@uX56(DtjDrDBQV#GT9Bn1OzMX>o07-tfIZam;@}*A4fJWxjEA{mN~fZG!at zmZ`(SHXNkTBzkwrgZCG8K5XPbL*2tpD{riXbFx0{4kx7|i?mi$#Lt{nukaA7 zhYT>&fp(AG*~@iA1~tQ=y(~){aTu(-739@`Eo=wSddpu6X4tg6^jDx zNGi4rRFrB6(1}#cD6KYvOQ0hHdBI?gEs)mK$2%1~eG-u1L!eb6;zMRjz*SL?r`0SD zF~dOBRyQd(!-o3Dj%;xz04fXqHL8{FAhMnrBR?G=v@74+ZUa6B2?? z)dqS!p;>v<;_Qqr5_{_nzu*EXj9a9ZC+#?|s3*<@wXtJHD2!~ue>nH8T|dvdoVmtK z$uR)t$*%Cl1^pCb^d+R!Y48$jDs}&{4^s@sHqvsvVQtthjJh!{62D-enKJF(GOBh9 z>uO#Fn5xdWNJQ5ZF3KLmFd)(qST_I(dtDgn@!9~_q9lD6eNhnhRR`r<^*G?Wb~nq6 zfbS|^Ngog*!zQS>W8=h1VU%=#&@mi}7u@X}dRdI9xMGOnzR~~24O3=Dut<)%`36%4 zkONeNfh8T##&)H;SW^UX$v2UC{U#WOG0uaBL2+}9s@~7hEbI(&OhWAm_Q};LUh?+d zx@ixCik@ax15AXAo+uwI{GCbQh4%?{?6UbOi1A3tsj&{|otl z@l1LBA9s|Ovy12d%OTkNKk-a?{{Q8f`tLRW&pcC|XT~o+-&Q{M(fuMeFamu6@f#gk zUfD~3^|Qye3go;Y7@6Qnr=O;7t1#34<~QDL*gkle$pIHFlRevhIf_JQ|H-?hZZoP2 zsxW?Y4nx+cA-K0Rl1^VhjK1(=Y{vZ9f;#F|`i;gcq4$@wXTtP;Nm~E@8yp>xO&@#k z{WpKmzdwe4&!DBcVzj^Wc!8;-IiG|T+UPY#{88e4=)}WYrmv7*pnH+_J^Ilg*f+dF z5-4E)HkyIz7*GZ>r6u%l`+YL5mm&PNF}T7DV30zZ!a z0QQliaQY9A17LBNz8MU!K65b0#Q9KesMSuEmDTPFKJwQv4UHfR5G*37Ma;UH9Hft@ zx|!AeuBX@Bi=iZ4lpNfjbKx--3s`!O!EY@P4N^y#b?I%d<3IRd#r*3MVRwCPNF4Ku zmi~P<^d+8<$;A_s8vv1_E-9 zt7?d+E&@$;Pg~TEQ*_@7V~ww;;sJTth&YC@*xK-Sru%VEA6rK7C)i&xazYl{~aMUE3nW+-{2OF=zuL>?XRDT zT|I8-M|I@?eE%$>Ew6m&j?ODLTtL5$(T*~ExY)ti(A9YY<%RY7NXE3 zaoFPZIZ6pTie<1;^Kp4HcAR(CEDLH$fYOU5Uj70l?qXX1;}h<;)_hyBBt0^<>L9_- zU)IfU`Y`|g{kxrNwAg{yzaFW)uIkF1ipOlYA5S=XqA2#|N2`aUp--uU zW`U*Rw<&Z5*X%LOv^^y!=Z`m=Pv>@jiRQ~EUYGwV>+?WwLeku{Lq^pCs^MnDI<@SM z#!ZGs{yFVeEcz{Y@t8ZOU?8sz_$!*OhR7fOg1f{xmr3jzeX5?aIOK+FeG%ALFD!;p zcEW}-9x$r4?Xe4$9)|HsF>wYt?KXx%)ZzKE#l8ba&%fDv4%0hZ`TfFGFLscXPqWzp zD&o#Lpx(HGfDzI+lBNegitXFgXK*y>*2Y0#@ovzA<=Ip}r}%8zw=fynb6*b=^sBc? z)bEvH*iVO^|6_;zeDxqWsOihNcNLYW>Y-)sPb{Av>EB80+B^d$w8F zrzGZ>Z)A(c!^-2U^U6=^m+Clr3UKG`0-UMGPNf)N(ZRYEIK8Mhs2$k7Fu$Ma5r29) zU-(-K^*o{!=9WZ7?>c~n!Qpgc2fNwZaAXo4?EGup0zM!pU~Ay~yBd=Cgl5(pAm(fV zcn}5~RcigT?}wD{W5)7Z6s1k?m%9o;&PSk3Nu(djJ{MNqbb)0wp3gcwRb>47Rndpv z9?ws5iBq7aq%IHaL6Db9Y2but0CzcySTzVma*5zD`t6xiPXU|==t1CMY*Fzu?9eek zs>sQaYD0*~4;D>R)PpDAY}H?!%a^ET*26wXq*-APQbOL^XBWNNNAyiAmx*3E5Wl49 z`4F2w+`;(bJciwTF_P3qcijHoZnyI9KmD6pLpMdaEduH!dVbCh6zhJTFzPs-wZBP<7VnZ>BnkgU4~>XDV0g z3r@ILcV-iazU1iAg!wrYb3`H+O`lJ7Gmt?{?spLL9KUGdv&X<3r+WpGK_$Z1_7J2j5JOd7!CRIF6G}s%Uh(G`6Uf4Sbq5)rN>VKmV+Jj9 znH=*4r^KNLWaw;+F(f#LKVh{)rlMF6lc6572{{x%V|7*8E`QpVt5Oua?-t1}X_hLP zO1{jHvw-42OJz=ROTCb)$^w#>(gMjNlzgR)QGrmku1pt)jOrayvJ>CdUR-?S$)ZgA zG#y3_K(cp3GVuzEW20SMcDJkP(an?mZVnjPS67V5O&od1ure3QRf(pX!XX9d_>k_a zFd@wSbNcYnP0pVlIf)i=S*g5`iTP3YZ=ZN3l(uLS#xxuO*o69QH3MHdrn zm04m4pT)<<4)8yA<@hT1++LF}>KQ?@k#%gWV(DX1tc(KtDhCzdx zHl#9tmDOU<3q7)Om?8^RY*`UmQ>e^pF`kA>A%P6KXW7HS4Lq7C2^6@9)H34?IW{Hpx3@P7L{Xvi_G}q66=B$0+HnGI{D}C%N z{*4v%Jwqag<^~~=v=vI@h>GH#hzaUXAMf`t!??{=ELP7I65MpO^a-s*)%6n2v;$Wc z0xLhZ@~q|Y=TcvYM3gDAo^fV!;}secPQ>_r_E4*G!?|X9f5K|QV;|fl>M=n`6Yes& zIXd4|X4n|?n}qpMFJ95!y!J-Jdve{aN2r>fRL3s)AoYez)dKFM!U6Z4`~fB^#`C3|xngHWRUNCda|8NmnQGdN7Cy>;uz zstI11VH;mu!+a1QD-LeDy{g}paIu>$CA8(=$KNCNQ)Wwu0?ZJ4n=^l*oZ#HBTNz@o|p6TWOsop8l zh)ISCfiCTT%A@n>qm=(52`1uXbHY?MPi>)8ZMzAzG|voE>NiV&1#9A}JzXd{^T5qa z>!-W~HSCX6`oR;Z@sk=fD<^`E>DEyXGmwAkR(s;}Df{vP1DrdnVJd$r{upByS`-@F zWtKM)nI6MqbssyTqwRstKPicM;5Mh$(DfwM*^jH;bjyaTqt7O}aZ{QM+_C45faG(4 z%TjgDGQA`Y0MXKk9UALXxTFgp3hp&Oguup;BC`pE-EPWbiQwEPCfYUl82jA@TKs%% zKZWrm+WQ=?OFNT~Vbp?WlAeeAj-OtiE~dh)wCWj1g1ZLL6qD+PBXSpLmkdRjuS?HI zf+-4l4$~GN8i7-*2cxGb#bLT-`_uZcv7p{z8u#Rtn_EZy--2LO0PV#q`02B+H|gok zT6dI{QQ?d2RBWD>T@=hQ>i!Gb*V>;PX%j(56rpy;aQAd}njjuT;cGw(sR^d!QQ7-C zZ36B2V`qi|%nD6&b=#e`t?!#>N#(Q%2N>oz)c;;2aNpMvV$9ODoSH_1x+s;Av=`3d z-)x4P@esE{^#j{Be?4W@P9wBl-F*nAjXwo3JQvp`DMWQ7qz&f=K@Dg#DQ6jBl=u8D0u4wi+Mp_+}O7HKtpi zd}HkMcfS%fTwZR^$>Ce_9X8;Qu=Kgw?@0sxG{w zn^QdU+iw8KyK%FjC`%b1Eqq@`q@et6n(}sP{r%No-#=*h!iB24KAWO$aG1*1sC9tZ zMY3O)!OM!R-dcV8V%*g3)YDTKwH%GI6INaJu$KpKU7ke_d%YOm_i^W&H=QqpRWEBa za5Pf~a#uP`)*4O@2rUD|*gAsxX_}W+sx!S2d8+Bo<|eA&OZthct~9u7MECV%v&ZN| z*G;f-u8g2VQAg}frFgYi`Js*6y??54d3Yk@=&gvdi04uM{Z;3@?Z=;o-flT$VsqFF z!&tCu=318$+)Tp497QHL68OtKTzUTpoMy&H8raBODPTRre&A0^NW9~iQhP3 zGp4QtaoZYWvw!mr@b;)MZRZPZO8Z&28zvZ-kc|+HV@kJ{p9-%FTVj;|bvOJH=!of< z^?^AS`FPlO=G{@x(`a|&p8k>MsMhWdMM$EC?T>mqnW?DY=lOpzaPCgL<&}?JtjG(j z5A`A5Nxi=E%17Jn@DgYw>Gn$O(9d6)^{7tJ<6-})vnLO7`0=gd1Fw-e_srUYp<=4_ zAZ9Q>#kSP;_o}_dX7(>JojX07PmE)RFkU2nUf_D(HJ7~%3g+i;hr-IgOF3;{XJuw z4{JyBaciwB)pTmqXM1@rBs_d$a7{Avg+!n`4z#IMoNgJORV`ox-H$mqu?Q7;d<-AR zip^5$dq;s67stj!L*`lY?y`@P2~{1a_bON`8e9XtuS1$rMe^;dAy4>RP3Ge5SW^G& zCeWe)txM#1V*Ch4B#9pi$z8nN;v0SL3>ZsjyW(QQ<4K%PzjR9gfJF`^_uqwD3j%;j zxKz+P#D6!`UKAVEk=vC;f;Jpvuh-) ztG_xY&t>ZK^CkzAIn1sQ?WGy0K%t^YK($(y;%=MrH#r91N*?*hU*!F;ufezBZ%E#4g=8x3jI0Ne zLBg;z30cu20d?JTo-9EIn?8ZDy?7}&V|Ps5;p-EmIMEQHSTP4Ir{rP|zAuo^QC2w> zf61K_it+gAxwot_;7^B%1R7%)?gy_4)w`Mx_4vuzZl<(EC4^Qdh4D(ZTs~MlOtKvu z9AN+Zw86$asw6Oq;$I>-+)Wz_ayQNqeZjSz@}(p3JlJi8BACU@l*Wg|t`(&#=ti>K zx!$VG2GH@?58C4pjM3J)*A^vZ1drMWf|y;u3h&2mxUHJRhb%YVG70JYmne0}ySE44 zZdlh!jC&F{_57i!KT?3f~=j*%-|mM9y50_%w4v_qkG z=q;LCpMIef6pMmyU&VhbBL?}Z>C}I>e|6_pWyoQriyPHF8rOQ zmw|YahcQHwIe}dX`&iiBz12=rr?9Za(RrPkq-*PEw<&SJf zta^cSp7$Dfej`%Gh&N3HyZo#D=z-p+f4WQqaW? zJ?~nHO)oXV4s;Mb9@*1!Ts!9M#@)d2Hy7ddc9(k57lexQFz#Y^)%_A1*HPVz?Pl75 zFBMkvdH31fSDu_c^or@ zOPu{ox$e0HY-4$+$|CLmFvTMG>1jsV1F^XYJQNq4D6EO^e`_;zjBJ%j1`||@R$Unc zv8L4kh99tYN1ZWq6fLxNkzPV4y^d#HS9}5mQVo^AO$F?u9_-tNC_4JgB6^olO0u6& zPNdrg?EJ7R)wI~W-n1R73#=gY6QF)Kn+m^VVX&U>SFd$(Hgi0$VRu}rb7|_83pA|? zL3i5N_{)bM-4RjDmJv?R%12dR+{t)E<(W4oSStDkFh-a8S#77hf(;UUfa}}QEo6I{ zl&dWYd%q&pYKsf&R)lwE*Z!B7=y?G0`c!{@Ys{5pFU)P9~3i z_mXE;;f9UBw)C1__MQFx6}85t(Ub`h&8Bk6G|fVDH^d5;H03LfGd3+_kYbRM)y#;9+Kga9aNVEz z9ryC!e)fCtf5zc~8(e&@_i~=E(=(;!k>+;P3hVaEqN*5H#aV(T)x_T{1@M#VcDK>e zBkHWSNs(5`Rhxjd1>tXGsTF|pqNNZvy`pXVl>5-{24Y|Va~l=PgYiI`1jwS;j*3|L zkR_ip%)OKtY`*JU>MQE@OQ);u2K7$fs0;N{#Ni=c6dR(G>_r{n*Z~br(G3cTJLa`s zxic3;g&h$KY||YH7_iF^)do|=-g;fP-_Cxez5ZdVLn~{`UmuC$<~^c7uMJ@wcbDv|`J9WCN2@7Y7s_E^s()<)MG)2)_v3lcNL zda)j=IVS&y{qr4hR>QE~vR?yhhC+|GhDUD9UoZNQu@11)nS`KRf0XSN*euoy?moF+ zLubnkOm#+Q;%ev&MVEjJc?uDM_eG zt;l43j1+Y*sr%X8Vb!!9>;-D+O6f+Q`ue_1h+L)lWvdJd&X*SXK#ag&t){N(M~y3v zSQchM))w6eXi(KkJ0J`119KGdP;yodpIQ$o(jFHqSqvp4M4n|s7yRR6E6QNY(!Dcw#=K+W>A}$z zE^q4mz)=RRZ-q9x2Ub_19Eka9aCeBowxKz$9Fp(&0N>>s#WxZr#CaMVj0Z9=6<;m< z*@bt0_X9u3X7A`$RVh>eCLD#33=i?wKW7F*nPnJC4jamp39EGMIRk8Uw)SX`<@d3% z=fdzV>xW4d?;H6WiNbtqV+!<^oyeYp9r70SLo!u2#4KR0EIrwwhUU3_LMR@Qqg2nc zdp|z5@(`&%xe!waowBV}q$gA+Q#qq8_yinBp zH)5(gUGS~lWMyHBeG&xWGDT~bMDTKPDS2K1WeAIyVCa@Nh>HdOB(o?cZKdza;t1&& zq>N$Y%ee_kMQo&c^7}?#Me3b|H1JZ$B)SsCqW$XnD2fDTZUn%v*(_Jk@9@|lyKA|0 z0Ft(Eq(SQbVG#7o9Toqt&TTA}S8Dmu{@E7oea3NNtD@=B`zNznG+&AK744 z;AMPy-)p^@Du}m7qcKmJ;Gzws^;h!+>E7iJ4GZt*ESbcK;_(WzRwX3NT-`%k<>mqj zN5Kwe>j1=<|B{o~%|90gwf0XIRN2+$zNshGntS=^1RkAo2EUD^L(iB;C>Mg?{s%oJ57noxR{Z94w#VM2y)V5h6Tt^rl&} zy!iNvwV7sT%#c9|}r-gAs_AR58V3&v3-PA|h zDqLwQQN@5OPbgE(bA=hxrD+uXe3=qah~Y}vJX%t^S2?S}da%tT^qtv6U+Q>}rg1}b zV_fRJOWA@XP}{=y!P~)lWjiOeJC#D6rB0mH-FG?Us;%?fL>jTc=wse&Fn<+Vo%Si# z67l+HgYiWpu|2$EkQsO0&D?0qH1%$(3s1nRqc;#|s-yV;BsdP!d3vcEJRmN*6_1oW zfct2maviXMaIBxoOSjdvtB&=S@s+!`5?RYv_0M?w33czEm{2^9QSI((JgYI`q|0i$ z&*Eu08m~`}9OB@0T|J+JO&;vGuYEw&ZFPQGM+mZvSdwjO5cjqdd=#l;DXu3?!p5;0 z4LY{wSdGTG2ri;sa9>XeduKub`PY}D@7dMQ2@?m}D$vAs>;YuhEFJp_?31G0IJy2_ z(f*!5XQ|_Gy6y1hK`S#|bz9ah4pY~8AsDc4U*i&KhLf?_cH+MQUpkln1F-SNTdYsw zOn~wM{^06%uv#^kHGn_x2`#noOzJ|W<{?UiVbjiZPPgSr_qmFSF0AI!zUbmGDcx^< zF3OqMo&<0)<5~x^z%SQ9!A%@?!mnd%24N>?O@FiDE# z{zp3SefGI;38a5T2AQW)bv-fvkF;Q~`~Mel;JN32BQ5a!KO`;qpTGHkB`rW7c*y_| zch-w>zXzL^%bSpozLL$nqvg`0Iz6Jktq3yi^xyUV=Qu}(8)r47A z<#p6m?UEQ*Y{9W~W8@WFf3ELFS>*>ayHq z;G9>lO9YxBcJ;c)y#pO;s~XF!A0BsggQK)Mhab%)zns4vxq7+ztX6Tz?zRZyzi(LS zO&|5BnW)A^)Wx=op4#PBw{%>Yu$Of;pZ(!igdO#4RFooTs2#ynz1*3-(3DAT$NN<3 z{De@oro(lcg{>2R&)4>d`HaTXu zGkm}6ftwhc0Kchxye#;IY{1sxiERfF=LG!`8FBHY;!sw~-n$r-|0}fg=+2xRZlQSJ z^d9_n=;U&Pa2PzjJ{5&nF!*m8FR*4fIM5@+YR9Z2x)zSP2#%A32Vwp*iEF}0*-}mS z5*z>Fl--(z*4!)}e!6={4!X+{)@U(t`Oyez#Uzd(GalP5Z28ap*IgC|ZuG;lJZ{4UiHB zg40sGLhO*h?iP5M=FYGTn9X+^*X4Bz)Hs<(o;<9T&{Hm)-9J^ zbHzkF`ty)g!nR2>8%0p0H04QDWq|Y3D}l3rf2NnjS!+^~-P50p!(y!I7wf-l9G`?+dXcWL96Ti(e0$fBUK=mqF`%jT+9M^I?q^Pi0O1h5Oi6*7M;bRS9!; znNDN252ul4p8l?DLc?Nv5lJ@{z*P~)bFCkU#9o`BOTB<9duH? zrJ6bB+anBD9gr*M)}(B#CO*2#k+A(l3BxUK{Yt ztn-><;8*9(G+W_UO|X>ayi{jYL2+};K_M_*kav)0 zvdyuDSWI0wH0Uc%Ag@ZYCe)*MRF<0)N*CaeM8(OUZebHwBmf}9ownxi0Mp2BJizJ? zn0eQE?8qBe-<^e!N5=i`E|; z(}I>pmwHM8)-tBZeMiFAkm_yEvKL-l0Il>v?}k8_FTq*!4T{IrE}q_cxEb$4HJ9iLE4N91rrDE z4HjLd9jL#SmNxaJfFN4^;smOE5`e5PT%KdLidfq3whF$uf$%(hw^l7wG?F^bOH=Ui z`MfmsbQ(EZG{aS^)t$$TI}%Hm4h)t++5=+fLWLg$zXjI$o0TI6_<|TDe)Byt^0r5U z3R7e7NBlbb{e>t<#g?{>`d<^5{xRktXCIN9NS)Ib;+P7F46hwn`PF&n069CDK0j~B zmk7D*#h=ze1mD|EsPf0!Z03@QEucFo*Jmt>x?7>sMJ19`rOGI!{N2EeWA_^C;J5+q z7*u(6>s#hE3g8bZ(-xf}xg*S&k|@tM6ZylX@hXOpA@+3|g%DLnOXL;EW$Z$8vgvnziCZ)a$ZSFGYmMIl|w-)uSl zc7%N1vFj~+Rh1`Oylf;39xr06NSsbq5>#iCTGSCfV)dOP)OsU7G+u*6udIb7U%jhc6Xxm<*OYXPcf=Kfr z1B)V~$~PykK!i9Z&cUyL0yA<*lRY3J2jlP6jjyx8%qMU-aprO9EVx{A)X+vtzsZsH zXXNCp!yf%rL}q%rziu4RBukz5MJ+wCNc*$XrqhwFP}-c>G&V<8-}#-y{cQC{Za$ei zlDN8L&Yx32(!4~jG9IsH6hW%p{P%sQ}HgGmxVq^Fh=!U$~LTXEEZniDcq321x4#3SvSZF^e-gf#%W7lbyio zSi?w`{%f}mT0(MnoLQY_)sqU{I4xq}+rUc;g-i*Ej%#O2rSVLL6SGK_$Wkg3iV^7r z0zf*IH+(BJk|TXvrQWdXcCWHg;q(F(b;_0Sl^*Ne6v2}zNaPkf&6EMhCe@d@Sch9Zl%Oyr-{^NO4u%mO3d5c@5~S{y3>9LjPW z#`7G~K&Bj?!cMda2p+_?>3)atoV3IP{bNcTd9?Ata0Kp?}sNa`)i9% z6=PNHDcj%p^xW8*)7F$&4``9MjuG3l2SN?(vctey+{E9yOhEo%TSlDB>#gVLr{08n z!8qrmPBGkg;2@={EfaV}6aA;-@gv`xU5GTXyAxfzwLM34AppQmuXrOEc4naf5HJnn z=)KlDP#>ObW7|I5aqM)78_dkg1UTKI-FDqDd}X)gdOD^9jPCrsLM!*|yB~-tp6LP; z^?Kc_ZYE$c5j_=rwoMSnSWaXd6ofdVd#5qufdD3Rm&H5vZWibOic{>kba8h$=nP7p z`Lwmpl)VW{x2$|?^`_}(Tr93r0|kbW4GSgMlD>kd-o8+`@etx*m{|ystv6<461ELf zZOn+oRQEnDZ%A>Qr5BeIT#bIlG`bp2{+ezx8`RsN;4lZT2U2$Ix{gVz*FXZzBl?)vmcQ)ai>FMZ5lzTvA?O#;Az2|6 zoq_O|PZ}buUKmFOK0H*J)@m4M(Rs$PcO;_4Jo0h~(YU@1dHUz$oFWY2@CQvfViIm1 zU`p_+*pU)hei*$!u-cXrY-IKNL^Uu625$%a%mDOjd zTFID$J3hP#DHxW=*Jyv2M7a(-K%}(M>x+(N=3c5aGyW70KeWXNONKr?-9gV~tMZ=Q z4{g6`+b5pcJ>`+8#H?izTjO3l`x|p577eKn-q-tk+c_75iMtP)&kD{tU+eKJyJTRp z6L;(@>XZWCmRw`ebq~|BSiJV&DDA=V&beb<^@ zfTXMO#jA?s6hG?TyRd@@M8y~Y7C9T10lFHw6%WajPkJ97^FU56TGstOA;Y02bG~Xz zF|(R>J0fUNJZ_-vr~5Y}8Y>lDfZ?~)eI$PHw?X>zQ&cm{Ur<@UmllV@^T8$BelCk+ zn+~W&m;(dt)a}Jyr8v~n@d$x|lU3>OFz-zXk{SL?&yDtsvM$S;VTXEK_P~EwK)f!- zUPprF8)XABf6daA;^y-!(?jQ@bv3wI;;cqHR78kfdPFg7$Lo)kc7eZ}>NtG7`MhER zTk&!i^2SY#eYQi8Lfm*`*Ck@*{#y_HaHiJ#kJyM5Xr<#9UnV=&93W)qWu2GxPaAsLUZ(x7Dy1=(p=)5A+THZ_&B_-)AMq z25GE9?0oUsTpjF)HhHwRe@XUs^4)LwVb!44p%-8em}NIo*6ZQObSv+at8b`=mKLI| zIgy=IK5z3YOLD3f3XadNFHkhc@^BA2t_WcrHSBcP15&H#4|~4S#JZ2{8%&Ogzgf=7 zZe%tEK`H z^r^z5=Re$?pfn%F{arks!F}>g*h>8mPR%iIysf5gd*x1rr=VvEDfZLi>ponpH*7iv zl4?|Cpp+ypb}nCa)g+uOV=j~`)Yal;cV9fjDNwU>;RmLDyrfRWR)19QM>7QU+?pxu z{QAF*(aKcTlQ5*ekhCw*zI_gqur&V>dmZX;*wPRxwFbI8m!X@>ltWisWU^p$9kTFf ziXl|_pJ5d=HGFD0ze^=o535B{?TqY!T<(zW-!4AFLi*&jAodAEDS0Y$Zj75XSxaK% zt66sj(X!s#cQooE6>9OcOyx6r`{p)GZ4=mlu=SDn&wJQPJ@&AA=<*Sk49Hn!pzcaI zKGR#@rVJ)_Z7g^eZUp1;gZ6W~mwnZ0UN=wLZSq%|{s%0|u0j6{(G>diLp@LSQ zpzn?_2?F~a(2$(>cTUp+Tsgm0F)&LmXUhj$=Imtoka-@yR_(LtD6;vj}AXsIHz)zG)2B>Vg>VnUKeetsO5OV*}vhNrfk2k_I!T)g81j+*W zwGz1$WCk7G%nK%G*JK4t9X3y^gAz)=>>d!^^AHVCw?d8HqT>~02wH$a(7-1bW#4DN zgu-by#3gMA0nl+qIZoP*hOM4|uXn;qL)`#Ffk;!C;x>Y`)rU;?dRYtq+ z>YoL&6-leSHsLrZ7>_AWjezVYM)?Hm zD75jaf|qB5rG5BxUnT@~#rLsWrDRBi9}QqX*l}XnL&N|YBKKj5vcIMTf8;L7HjIlH z1*B6a{JKKitpfD2$P@7rP)eV^wkA>zF!CX3^P4CVB+%xoCHG2mWYKIfGas*;po~#- zNBIve);LEs*ElTBscOUoY&O~?5m@3>+$i;^2skfK=+BI**^@aje}&BNVEfRX{NyVd z65zLp39DZ!R6P*6pN}8NQS&!g!-%y08>(JT%xeqSr^~V3q3(_-7BVk#vclM@oIrg@ zj^M6yzVIl39miuKv7bqrXFX-(=gn^= zyfZVsNwtX++5LC&=DcE5am=W+nc}dgFK0uKk$hPVF6lAI_i^Q6oSZB!F9k{16iN@9 z4eCR*X%VEDVu0$2ZCGt>agwGktA_jBTJxVIniJBv8`dtbfL#Q zUnH;9v9GJnX6CW<<-5Jgya$IvS$AiT2*-wxAc=jJa|d0GxH)NkQSpfSuYifB>>+Y$ zti&Jv!V^p9tbrsYD7VqoX!?PX6b6U{LTovyjf2%dc9)d zMs(08KwC17tVSp;t+yBfW1=1Hrui#Z>k>c@i6wXv{0XOCe*Ky{X55@LcjS-s#UvgE z)8Sfv5$=un%fzUN7p3T}PfJG2870EdeIbrXU{D9Dl7FG62uih~wTXfKjYm5(gT6T# z=lb$t2W%>-JGl#Yl5qDJ$cH*~=I}Ty?eaRWw-~<7l?sci>vTHU6!GHc2b-uJ^cY~S$(s@Fh8T4>c2D=a`6)DujGS|equRC@PTU;%vi0gj_12@#LQnt=kYZY@e!eC!(z)P^XM=nx%sUc)W z&V2V&FGwE(1z(8eiHo{cf1dFogZhN+zDQ0^~ygw^d-hMBH6Mf(!lSx^Fzmv zJG?A*fO(Z4(mfLL@%no>RcGeJIBZXEadFFRG9F;b=8n@F-BAgPR~Kt~8Gt@ozM5i{ z%V{gcdWHFd`g4ynD9BCFzul+kEbZ_#!eFTYGDmmK`tQGWYMIT`y8v2|1X6EVE7c?) zcM2%=x{3QQUy)?CakEi$?3CRnTRj7NN!N%^8*0wyxWAdM0{C1pq5gz@n_;`qlTu7c z*NupSLZ!6mO+?(fdFB9A62o4A4F-)>b_3m(8z=uV?$Ka&&|*XHrGtjFCIihpEH5q` zz*{bfv~E?r$DN)=(JmzyEJ1U!`Sq0=5A}3WExkLK;D7Jncmj_wkMx3j!7b2pbZnpQ zG25#N#Ze*GKmEpcqs)vEQ;nqyo5A;3b}y|wG; zIggl@xx&~Kw_5ypPa2XmkN_5jB9(%h;HZRH!;({yEi*Nai3&WlvAVLfBF<XSEkT)+4v5)0792UM;Iaq&CEZ}N?VGkS*E^mG&AUAC z^zl^`LKKLdsr_Z&&yLj2-3>#~r_;*TQNfp!d)^7tqo9qv!~=aT03@ImB)nx(`n9Xx z%HkqN2Ua&eG1YS!b26zDlqOT*rNFZ@my0PAWgB?*8`!_8=E80HeN2dCsAD^p#*~h0 z9L6)NzGkY+iVdy!Pko_2iE<=g#nC4DFJpoMI3c*_P8ZNnEITSmv>kRxynRWCt(*hN zHgi5QNIOQ2<6`aSnm#cYwa48J6kF}eKQ$=rYeFZ`=$8H+N% z)y5l};vxwffHJ2I#vy5jQq8d^&qJ97GjnkQft=l~h=bjjDMuxn7>ym`VE9RVCj;Ol}|8)7Cz?JivpO~uyI_|2?kd(*X;6nF~o|Lc^39W0> zG^1GzQ@Jt}lq!&^05Ocw|LH<$p^NN(Y$ki1ozV2Kxxn&;QmdyH^jck<=&qW~E;ZC& zQ}oExmo$=_uPYMg#HcF%Dfs;I2Oco%;}VYCVSFN<#8f3U+z-01#Un#l3CU3^_(RuP zJCJic^+_7(cb80AUNn@GBSOsjQUMCUmfYtm+2xGkA3qFatfwk+Ijyt92(QO(dI4~% z6o9OOX6t$!5RtlxCsaA}oZy~5Ra}hxh5%s6qiYFHJWimSu^V}b z4dX?Td?J#8F{caQYZ(2Vm`*z^l ztWx$EqxN9xt9~qoJR~fWX!k>8oX*{Wl8zj z1elU=!^kA6Co8Y%=1q&TvTIS1rA7t@TWF6mvus;xgR<(4G>n{`37evI1~29FJMPBa zTYlx-s>|XCxJl25hk!Tg%fVQ`F__w_%xf0gC5_WTCgX%<*FIN@#N^$RGgjrtZHK^>pV&MH>pyhG;cW&5tKPy3Z)nda|3cg&X6F(Fk{`oAl-p3{jCh~3W(Fa2gbJklH3B5#yBw7;LZ7B zH5P#I5}DlHd((&vb%hEQVh4e)bw~Sgn__znXALb>D8?UCw==X&t8#a`UBK0<^C8II zo6%=}e)5$8tf`uIAsMlw)S@uzBVViSuz_op=OG&0%yQAp@+o$17EnlWxifQuK=(6P z>b?)BX~=V6@;shxLDBj2b`}_<&8(hPQ4A+f)cObd)E=#gKZE;INE#sYi_%@UpROp| zWoZga#YKRuoFnGrejJU9Js4M4*Z-FR;koyJBh>ij|CCVU-#_|)CDgE6w;uP@(xP}K`)zfz${Je>_)2fn z_ng~spnlTAmSDDgdR~?VKd`0qrrjdRr_Jzo+(#=$BOZA!i^>x>xIr-i7BS2Q2H(#lge$ z(zm^B8+-KQhqsU3em_=>8FMr}8&0);;J9~B!`FXJetKTHa7#nCvhH_-y5Gys96A%W z_s|hI{kvy3D*e)1gqCMpNsBk!4QDUdF%EPgi|Tgzfs_C{Bml&I)N@9T1}-#jgHxMf z2#w=Ep})fhovpkuZSeRXt4fzj%bK$nb>1aKQX0=)|NEScfwxU~#e1xNQZOMDy~#SF28WA(OT; zXPAd?6h@M8L73?*!}U*}S-ewT14$j4_!hR?1Q7m~|&lOQ_d%{_&d2(z#f@*%!b=TMV-ABZEI@csK8{=_gCM4;G$l2BIlt0I3 zH$dj%l_F?r#c;JdLndX$sy|U=>Y^gc|Myn7}i_ zxDn(z{Dzp!9*j5Bagoxfnf%j`tb1s6mAO7w@DeSC+HQBBjDn78D_W}ciC>Jm2vQfQ zUrf&B?6ORJC&6Xd-^66ic$2``6ohBG0ia5#fqc%Ty!Khu_9{rUKyqy*7di(LRNnQ)3??Xd#DRqwdLjK ziSc@-WzT??yQH^Py-`4n%i%*kY!x|w6=2E++Ya0a%$?ZNvcUf0q0r96t2W0MH91e= z;{^&X8K~Za)#BYB#TDyg@_Hp{AihAPqE%}cg5Yn2XohF0gb*lxzR^mSk_qTL;`nfpv@fc= zKLFpA*)F?vhXM5STm^pviu~7qiHD-Z-O<}`t5hYk%)WO#xEH-R4N)=_t#wm)Lj&kz z>w-@0o{sWlZzy5R4Mlro|3-ocp_EIROtvDimZyRsd|Y#uV)O|rV~(sOlXJ&Fd=jZZ zRYt1on(o8)-{$=r*;y^Vch5BJG!@nFKS47@JSOaeyF;lp?s|RGBsEu=3i3aK70O_> z2v24g$oPD6(M$th3g&BU?%Lt)ZSJO5$M1(ky(;~slkv-R%LL5AzPC7x0~o*GnQ2i8 zC05TdU6z1?>y=`M%oTu&?8rE~W4jabWz2oIjhyCX4gcBXJN}xil0k zb|Kh?=_YYUF1_pDmX2=kUnUsXPJx3+A>QnOpqOh@s-obb1gAG_=!8 zQQJ;p-(V*CC(o{+W+NxuIsqQ64UE7z$!M^KjA|qwHAtczu`&tWn}YJ!siDXP?E=QW zFsFAEf@V^AK`5FNX)HvzI!#`S}3OBZJm9IwjQP!W)9{+y~{*a1$do-jk4bBr~m17bm3)*R@>Yx8v-si zWpQ3NdIA+eh;u+B_YFn=REHgi@JKJoE6va5==!wq0u94~RnsHcCfSyf9B*|sVyP); z&<>?lXE_<5WAH6 zKmK_$-1XPeZ?7U#F!x+bJ^erqy@tV==pDFI2FSmX9~mI8)cmKU1a3wrSZE$7x!NCs zx#=C7{OR9(*Q6%bor`X!&Lt^j-$h<8(?GNZ8-&AYA(6<=@9er?6L%OqME``t+=|6g zt*qWz106@%AGgfnX0KM1U1?`oM=^#Jb1f#sR5MEIw=Im;FwYE{AVy^$6zy1@Ph4QV zveB`JnU{4HHc#SnAM9Mjgjws*QS^V2!4Ka2*qc(5bUz0;9rqpZD?Dcqk^1-4g&!*~ zIOgj5C&L`Sbwb=kAUZQE&4<1{+ZJUSq7VCx7Im4J-F=}a1ow8Mul z0SqE}>XJ=v@{6Y-lg+y>g{)$~Zlv#wl8(b`e5KA^*XbpJNp)XFQ6k0xk7irX6 z#H_}of*1Ta3!c1y8pzXo`MR-Oa?2G%e|a*6&E-XON9yTWOcc6pFNS+AJDyASc$t^m z_(EcLM`iuc0A?EPVC{)T`Y(v7pN&c;Q|mPwmloEt6sy5EiFP6HPCC3oqn~dMS?loe zWT_o!Td(noA7%6%fQoW~Ve|#n0MQM1GwUyDjV_xLN0P@6pZ)9fbA@{FIKJY6!_SE7 zho|h|rT}9b>bC5aRctjy{R#c1VbOtM`cvg?Tzy{Kqmz1%{{ZYN5x^YzyW7rPtkdX1Kvc+nF(v1TgmXr>jWe-3QR%sV5n(jI? z*n#$YG15fv?hP?=3-I(ZKT@_DMgdX8pImq2ySwRMX1{~&n!1O6#z8-OhJ5($&NkQU z4l&?-`#~_%{nz@DQnQL*9$oa;Dc9WWiTpQ0$Vm& zQY`b6iif8$UB>m1uPwgTU9?a3=}R%!xhy4)PK!4nH4teITUsvO#&FVb_e--6t(#eA zO>uH>r~3g3GC&-L0Rb=7^pzFG>a)pd8?78I>@Rz<)z>^-scBnY9gMXE!LqNLx7tmX z;l4jP`#d@IunvEV>Agg-gfjK)z?AJDhk3GeeKv(^G{yFo6%VY3$;;-NBO<=Iac!?+ zt(4+TrG+KDC8caSfeeBUlXK~f6?a=2@^xD*#_8D3^HbRM^&{ImuDrI$MQx6V+-2WZ z4>nTT5f|HvJ;8CHhXyiPB2~P%BOANB4*ld86vp)(%+${s3nyq$3I1|}odx3NqmfhS z*_3@P`YGu3T?S3Qi1BbWWfrSoU&)B#H*vOk5lxT2MqkD>P%T6oM7u?= za4UI(%07*esq&icu_UX=WiAjNtYwEbVpPZZZEwy74Y0YhmWAT+w+oeCl)OBw7lNJJ zDIKR5Hy1i0V8Y4kDc85`cipvk{isGv%lu?K5i@S3SC7@;=C!g}cQ$r+%_#9Pf$uiv zYMO-Fhj4XkaUQN7AsHesT z(#hTW<&qv7WORXMAh=B}VM~H!8O0~(Vko2PMyWGg)N`T$1+ z&7}c@9HfL8Q3Yz;Hm6lp@loc~bSqxP&~Rik(iHMlNSrWQJt!jD^H#6nC49NoaADE? zbLiPq5EL&{z52-_3$Fw&xs3t{N)tez_vI^qyARr>3<0GpOC5^Ypao;%MB09x*VTmo^s)j&hKAyakTgp~Ti&*%y~^Jn87&^4KS zZXdI$--RvP(Y1Y=R3s`a5|p_NMUR8`t$G*0OxUw$d)P+?Ufcni;#N>$>+*nY6N+_N zeS6Or1Wnj&Z}n{S)yH%5Hy9VNWc7#Lmls_wRCpBCLJ*O((bC~KDj(R$9=3@dWviC= z$)L}>@0dX#xz>QqU%Tf^Uhn(RfztTooNra8H`@Ohw&_bXG*-w^hXjalcbGJDO-Qw| zQp+5zwbk!2W~U|gGZ;+hEI5=`7N3(Bh9#?TduXlfekOl<&bKLp8>&X-ji{bzsY}TS zHd!K_!WJk=DkUVJILijrrp-}^Pw37T#F4)h!^)xoS@*BVU8kXbNKL^Hts9FVCO-EQ zE~A!F%ADzgf)@+~kc?CqfmhK~szRuwuh9j{T)Vt$btLg{1ScASC+v%z(`ZO=YEvxR z$LG9MUH9!<2eE9y-|7Jh#@gHz)^|k!NXGa%MVz<@ny+1-{Z?Ne+!Ue%>HUoC_1ZrE z`pOIkIosyYTWwq%e#M{9|6I_V3k3LB5I zR`GcRwggWG4G<&`%pAhY1FtN+@)Z{f7;&x37!dC31680AZ``H!#I~CVLK=*72Bjr9 zs?U8pX1~%fC$$H}Vt(+K50FZtHo{14p^Ep&97t*7yIi^|$yb2>0BXBaD(A~p@z(Sz znU1Z}@>d|d7>^3$0P7o#LZ3>()KlKLnfSYNvlpl}<l93rMXtkuRe|`tvr$B`W zNR_)td4)wvJYbN!h==5W-Ep3nNtO|z9D_hp%3L`w{Bjt$XG<~lJafxkXbxc$3{17t zqfzD2eWaZuJ26K%O5NScJ@Qc$7qaEAutjN^!SeoLDOWZWR0x7}^Ch69iym!A>w{9q zDBU_JLP;u`*LEE}U&jK3QQ-=xj>nS5Ho>e3fw3`IjTr#t?U}y9x{fM;C(UbBhH;li z)UyeFed)HVtz;eB%>3wr)jl?fyt>X*T2rT|O8f6ekJ$AfkLGPPibgHk7tnB5hhN)W z`77)!pgiFYfl2>1%kKr+RBpO|veN>!{uDA4Y#ZN)nFTTK>#6ssO@e7C*88E3wAs*d z_E6J9i<6jO_Ytt|;H_p?r(d1z4$r)t%B6KuX9;$^3{+SHt)~%0uSFa>IW`gO|KAKN z>vQ`N<8fF)2MFP`&qih}xbL(>t#D()%+imYO^=UR#&&N_a7sIy2h^HrJH+?(-j3OE z5x<56tP2Szwgt9G%Ue?bKv@!LobjZC7K7lPV|a9L~1dytI)-oA5j)Kqr^I`B8z_@{2A)nVJTj({p7 z7E96j2actNUcVM}Z2biMlqJO&3HC__POhzR0{oBbEUwnL_Nxb`R=>GLcOJ~DkR#lt z-3F5?IFy_T4Py(^zWcKWN4Rf-j6TLDm6rb->N4}h4hc&4+Yj48R%rlubc2%f!?&)u zKBHfpOLmpOkObFF+JE}JeZQIYVoX=#Te_btY)m70*VB`Uu4b-B+eRdawwRe+HIuG3 zFQ)ws?(ZKs@j0X8;(Vn?61@xy!{`VNccoPL?=nWd)1zPRJNC*o!eOqUtvG>yc{(Bo zs3ZNqJG0r3V-ks7eB$KToSJKD&pZ_L3R2qgG#0kNlt zym5bz#EiHhvyF%R7VGA#!Y!J%#r$LIxyVT>-fM!bG6B2&zu}BKy5)5^2E91`al_)I zt0OSAv{24FpAQdiY3V6~g1z-@{dbt&CTu-)<|h5eCg9@wloC;&S|%0v%@I8TnQ5&Ryg#MqH3fcn~plSaRb}TQBWu(|_!*5W+4Z-KKs*0(nSmB=5uN4-Zp-_K|jj zNk&v{`cIPv@_G4%%XB}^w;EZN4K^mBfp6Hu_?dccP><+y#Ye}(ru%Va?bh9J6F-h7 zkkP}<2pR)z_fu+yb*^6A)SXTV2%5zXWl9y+v`eumaRM`44WAWd$e&pDFNzfGM$g4i+R>m$OKW+iZ8Kyf+WR+hybMdI&IZN2v{pd6IsXFpRo0n5% zp0BP=Gx8%+>Qpw;5i1gXa(_F{{b1S3Gb91|+1;-g=Krz{MMK$deg@An2m8o3jU(Q; zre<&Y#qkjva}ZYa+}#v)0E!DAai0}o<3dY=#!Io9(`{F%#CvGP1-m-GG40DRGaXBv z|N8lHbQVFEbDH}h<@mj<$){5}f(NHrf45%OfWN`M&e&{j%JqPmzCzoTh3eDywq%tp zUeUyvn5=;~V!_=Xn>4gK;tGO19_YioStwq?Fzw(4dyP&$RVB^g53SAqu%^gnRQ|9! z1hxc!_z1>raa>zMZ$0s)k+7}*&O8dl_i2j3$^tM|rk#RYsyOIc&+m@g6ZY3>1!&*e zvR0{MSIn}Y1G5Q&x(m&}9O_X*WLnl{gj-hJ?LQn&L&3emC24~UUUV6Dt`Oi%m%XQQ z#0y@DVv_dACS{PuSY=&bAc|ILqUPleg3R{>eqY~H#H;QK>GV4+Ry%7i2d z>XoWY^6J{;vZFp?ps0!!UYG2|<#P3(oG}f9*R~9%ts`^vF2(;}yuArjlgaWvJSt$= z!=fyLCai8i*il9yfC@qYSrvpB0VN=d%Hn_!g|Mm!qOvH63IRa~Vge2ratSWz=nN)8 zFc>20%n)J#9X1n^_iJ<(?;U^V+~xegnR7V4r0KWPUEN((UG+SPqYwBp9G{x1QODZh zyNFQ}=CM(`(k?a=FpIsX25pdv46}rpy|U0?Rck`#21#bKQ|u&^3VFXlQ!WVyOqeO~ z1P_aL*H=l(SvcnI#<-FvTg$SNvX$*q+{Qpf;LN_kQRX2l3kM%sGK(r#Dty|Y6x)KAUW=dvQ6dY9mnIiJJi%dGDeoLdgf_G1M!VYd?jlF%pG=jJ?J zCBcLzW2c^CY%XvM3eukb!19-OtMF zcWcc~h4LgDfI$XL_Z~29p+j?kvUi^6)7>$c)6U_?Sl2&Omx zlZ{ZN#H|63LCgzXu!62~~YcjuZAS6Mc9e73(+Oh|xW+o13sh)0G9bcyuBxTIM0Qvy3y z94nwpx;uk8p3vl=s8HGou7?zbbo!jc+;!a^O#*anxLUY*h6#xv znys*7!7PJF?`Xxw1+K-147r;gD!~ed=jgW}JwI9R?x zFNn*qt85|q2Yr#mEEbC$xiaL*YoLY7gOpE<5h{CxpPoGHUe=VB!R=sg4u!701n{)c z#$tD(&n(B-Nkkc?^I{+x9g;5a+Z!&?HW=AAi?JdISKHai!&wYLmdAC8tKhEz(HV+H zr1ECE%h(fKX7_+o_d4EY$YV2B!cSU7Otz5DK`EW@^12Dib67%bO7#tUVWUV$7R}A7 zQ@dG1WPXqx8$g~0ZcJ7Hgv()JVq#Y;w{x5-X*Najg4}Of)ZKO=&*=&VAt=gGa+u8$ z0~SM8AhFqRz?=^FoNb`j&F<2hD2&~ClX9F%g?_ZQNAZM3OvOX_3rk={>lq>K8q{1` zT)TefY}s8SdMtHZz>kELi35AGhRM)}>sl1LfZDcWlHLTR$0lQVIKb|LZQY@Vh13$~ z8KZLLXbLB|QDr0YR##zXl;i2i{WkEWK0Xmk><0g;R;gTc+>GCPzY5Ame zrj#4DLQohl0(9%BO99VKl{fV7tE!1Ewp3F~_fjY6C~Rr0ovO0M8Hx7w+gnK=^!)}|e>h6H<}+l#$f@)Txjzzxz$&V=TAOk)pGdygx?%R}vLGh3;<@67Ta z^i0~-pss01{RuMIOfxGkHnS`D+KAX!U75(JS8gC7Wk((5i8qaUWhmO-J-Tk+olDY*AOiM> zb6Eu-g1!Z*goO9N@+mqlz92+-4A>N>kK~~n@#l_25LqAz^m^=gwc8po5@74`@6(4Ui8Gpa2Bn;m2BQ6SHOd zreV>S3W^bYST5|+Ranv3R>OtcJw)op(P*Aam)cxN?F?=?-bN3VCHI^vuYR^6+YFUe zq2;>T`S?i1IY$1%rG}&*pIa?!@+3K#{II6&kS6>wDW&Or{-vb{Jom&0t{D7rI8_NA zt)pQDJK%CqSuXH?A_boKmJ8Fy#3=5os!+0Z?5U4*t~=5u%Rl8a-Wb(zaYew|!0|}4 zZ0|KQfs*jX3M^)7-ib2lJ!B&Z5dMsdXLX^uJ-zKI2P&Io*m`k96?2wihIQK=ocmA{ z_RZ_9ja6`hiFTyju}2&H!q$tR!7^C@^sixX+5q0WnP}*0U5bsNg{9}XRS`Fy%-3*R zjU(l|X&i-bTZ{bWMgP<2pZsq?nS+g~=n{t)=V8gGb!u84WvZ1A2Y9bT3^M>1ri~ID z5C_;WknWcwkIxg|jh<7=y1x^7&GE-QLjv*B?WDW)XLYU{%6grYael1SLjruuMAXT# z&EBFshVfIbZ!Gckv*mMFQxbu(*$2-jzTQ;2=`sMG15{P0Y}>b}#!R>UzvzuB!nfn# z&s5jH#$LNv5aO7@r$`9?;oI+_(bVkRlPS$5B6|`o{Y`hGR zKWyce*tityJl94Xi2hMwn~bT>N%S&XqLH?1Yc>PVA=>mu<4H9)NV)mkMq>iUn?)5G z4R?BH#hJWVFQanFV|j1(P`E~pLiNIK-zt!)$G|Brf*h86tz8SSHso?@daPe>46mf{ znTL<0Of?h@xyAEkR)s_pxK4D8ly6TTMo#qcX&;pw+OP1{?vt(rcC31KOZ%Na=(H9C#OnYtb8=w1nyTu~O@oz)X`Mc6lZul(*DY6> ze$}@_$VlYd8va6==?Iwg9&kEFXo?QM(g8_(1j60-*#po{x(_|n6~hY{6=bQXcD_R- zU8>jO%DgmtA)jyzA-$--fhY=RwTQfD2=sa=A(`GWPiW~KLYuKgkbs*JOqj`lMnK&` zw`49wLy}oKVB0b9(qOYV7Mx8U4U+Ji$t~SHIu~YcbEQ+-&1FBBEz2CpG_#OOr|B%| zOzqtGL`7@60XL$jQIa-F7TigO!twxR_>HGH{k?-)5F}-jhp;d72`usufW#+5%6`y; zk=ALads=sc2fCEjhyV~ns9~LKPlgMW$-$=qs5^xP*I1}&*p)n6)+-;KAo0sfSA`S> z#(C_xjt*$SjvlH-+*YKOp-vEH(vCP+0dR$TT6LN2dd3jE8_~q(A-9FHR7()`vhx=G zhe9*Lx`a?$UV^xzCR}axmLx3^nTu_&z5?|s0^~JiwH+IsKB}v}YHv!vTe3Ul=2kCL zc00srnyZ`7gL>lzZ}`o7j?+O7f(0}zD~c5pw`6KDAnbGdVd$BDdv6duHdo&dIw~fF zi?Cs7SZM4gzzHUqeWpj4>s1{%Zr~s?&ZI~ZM@m%zG((+$C*=t<{KZ(O+}}tS`2==- zg7khyn?Bcu-ZF$XuL5|(($euV%nbOhn0C$r$nWq??_!HXMNJ&Cc%+P$d7r@26%lfM zL9CIWJi_B=mSsRgxZI8QJU$`roW(#}{?;d9b#!`i%&+eup3#;k$$VSLp6L3CCNqRH8VG&2L3RH`4P!T^9TKKPsgf94oYNF1OyV?@ zVOBp*Z>Fa6xT$k9Qh_jzfK3u2UW0>ANyGR2F(clsUin`(_=v+=o1|UJri5Ya1U(eu z=5|QPa~z0_vk;201NNgJUtzCZS=#@R?r8ISUZcI$roWOMZU2j8M}TT&u^oRXDe4Hq z!qwFyAYeQ0m|IjtLSz&|*&-MpnG}t%wsEjQShz>w4@M^;tgOMmUGPaqeWQ-JCd4Hs z#7D&^AuPckCmc#R;-83%h(cJnMWx^)qIMj?eFr-6ii$r7dI5d>_sNbYpFB$>jy_qA zT%xp028Nv4cP6)&_}vxRM<>h!^URf>mRwzuRNy_9LZ!kkyz6d#|f@RZnxs^`7qzhL%o{%xWE_ z{QcF2R%@-T9UNkgt#vls6Aa47h-pejEXqsNrBygPGf>7jQ#?WM?vLf$XP!ru;%w)m z9fb+=DHjKtNbTW;lKhnLI}IK+!}2n(7@ix6H?51@LEsCA@^T@$gpgdmHOaoA!r!C< z*rKC1*I^nNxGjYkf99zHYHMZcEideQCzh<3sSa%5mSiX)n?kgQ9IlS%{K`7oz{WUqyIj@^lZe66a7D=`h`Y$RAX5 zjoRqu7USerMVqiZs6NW;W4nk0vfvND(?|q6$Fw4L#y`}-51dmKnz+OAN8(s2`K;LXHL)VlQa+OL&8i2%kdSkuYz8<2k<24*C z|A)wqMdP%UXnoqH2bS&70P^IO71s`}G%&DQS|nMw#I|OdIupa#_>Y!v3DCu4Vo3JR zyE`t%Ts!-Nv-(-6Sa02~KGoX=Yrzi-@VF*&U`O$qDDUeCr`xuAB;s?zLfih+WWVAy z2P$tYnPDK`FSIXdfEGwwjzM4kH~-BE*jLh+?fzQA$`%3NC4$A|i#xcu7JYF?7FU|J z&0-Tj@C(1FqY24JBBG8WzWo+qvD;^VOjJY?!omLYGV?u>5aAyM+S@JC;Q1l8ZUukh znh>7^Iys7P_{=`1Y=Mc2#N%ARkr@hFp%8YKRtWn|R*100#zztozy66|LJ}@13N%+< z>^16lq`bu!FGA)4X_PJSakh4r2uthF8P1=dt-$l=P2lshHF*Bx%Ph9H0ndNPwfJm{ zu(VkeYVpf1KHGukFZ;6x&tLZE0G_|>ZxeX_qCa~S!qWDO{_KH#wqNvT59G7`qCa~e zpY0d@*#r4(zw8gl2X@at<+BI!*?rj`kPm#Pzdi@@f$#9wGmy{ji~ay?pCyp-)8}7~ z>td6|aScT%Z~FW(n4ra0n?85G>2sf(K6hn_`rHQO!GCIGiTd2i67~D5Em6NWwEVpx znDWKmEG>U;X!*IJrRDGKtbT6?(&|6SW@+_%L#y8#TK(S8`g23&us>De4+cgsO@I9E z(^vRiP5wL@KC9@T=g{^;K)rrHgce8QcSuGB_ks-puWW7Y{ZZezL>%4XFYBr(do*Gh z!f;dY$zUgI_VXvcJ;qnGzA0aTssDX#ZTbVW(dMrs^V3NFi!`6wfvo&LPR0LQ8pVKD zW`7gN+B0IyQU9E`du78VPxks-8_Jd)5C5h;1=jx+k^U%8_)?_B(fwDE7Tf&~BKccy zG5kWLh|eOa!hZOQNPid+U^)CbXNwd4uOcnB`%gro_@b;S&#ePdi}Pp4vbGOgyECxQ z7Z%*tYp7Z(E3f;_)mxiDWRWhpuHK+BDaf-KLi7T+Y?Uh(iNlK!#bd^vcF zs`#&x{=OsrTl1+bbKONY-2bSx>@tLn9UF)Xyy$q(_rO)m&g+J6|MigH~fo8pIiPX zGy2a9(SO;|f71J-pOs7<_S4s-`ikOz-l_g3)&HjY8b_D?ljvbrDVT4d6r*O^iOBoze@F~ z<$tf}5r(c`D*DmS8$9(C?EY8A%JNS||6=++owR?G>VH#oL&d)~_@kdU_-fy;PM_tU zTK=U-U(@nWE&uz0GSqf=*VP#(%rLQUZC;Q`Xqx8QixuNT_zm(knlR8zE z!Zv(Oq(7DXi@o5JDfBmy{x>CeJsRd!+SD8Mw{O@PZ zHNyX&RQ&T^PUXO!eod-BRowQk9qN;f_&2HkHx>8v{A=z$@8f0YulP`wR$o)_PsZxs z1p42$acfsZ)#avtG+n8PjfubU>fBF?-_+fJ9r)T9eNDkX+0B0w>AzHPMW95B_OPMG zpM#|M`z|gAGy9rIe<(QE4i`UO6vXnA3I8{d{u2e4{bq^lH-xXe&-xGLwX#Hgv7|nE zh=08Cv%~v`D{JAOyg%ua3+xfM=mT4L2&#vX4=K22_w6e1PD`*AQ!+#aDviu}9 zSV*6}5#WQzeRj7!5oVubUdeIsM}bogUIsjsFP)W7&c4)nXWbj`JiKtC zbDK^~^ZSJ#9H500B?_CCENcL{TgBHA4xT^YU9=z1G%U0gG(e?^&k4nP?$>`NuKgjR zjk)a2L+H`n=SPjHdTlbh`V_Qwy_LJr@bgVl;UTK$rfS2V&p%zscznLEQ@c-I(I9@+ zMFq8Ur#l^u;pGY#>t}D#r=PErLk1eYKL7f%W`Us%4t}UGOY`-)yZKKHn+#;v-MiR# zFQwL6>5kvtgShNnJ>K`0?Yiaufp7lu__>Y{q*;m=XDXCM@(vc)Z{e$E^Doo zqv+QkSaK7o1PU#lDKXzV-zO@|<=ehjdJIR6w7J!u={5WA*W@KKhmZ}C$GelC?nkbK z>A(T`=J>ku1C9Igt98}ju>jA9$a-s)J+>tvWAgW9B!c;vZe)El`3 z$Dnl${=1RhI{8`I+WC|zbPXXjJymsrp}c&KKQSY0Km)Rl3j;6{P;&m%YTJj+4nNLl zUN?M;`oYZ_zI{`k!Jw;sZ)^5$n@Lu88Pp{~RZU5p=;^gk%ZNU4TCeQ}ar5=g68O4u zdjqcq+2zi@+ngDQXJS~cZ$dwQq&qura)Kt}*NcaOc>~jP;nG2&10p&*ED}vLDbjI= zBYs-zK&T(do}9$YO6gsbcjCCBScp^4C5JU8C!#s2HLP1*lL^zDJgG(p1hEG)*>nmG zlzH+ftQzs`_)wx~bgn)vt&<=DYK9}+V2%^m01oyDoiGk5dB$Q5dlIb0r(H_&`UK4*_R;;y68nZB^CefBJx*nnz-#P~<|GYcvQsT)ekcmDiVBxn6Vbo$hH2%$P32`B-aB>i|TY(8O_1hG>)$ipSe=U5Qz=iv=05dJnTBtK``wYi0+AHjHc0a%q_yASgh>0tpp$5F}~o!Y8#1+`V++ z(3)@_|J&e)!h6Xe>Awj8k4w8|==2OJMBqRoF-I7>yG_M`kRdS@gG{rLW{DFP@|@#^ zOF_K_#KHbTm`TIX`8Rb_km7J?uUYIgjShkTKPsjHP-jR`4@qujKoE^tG}6&A+YEGH z+TGoOP09B(d%SwV(6>rB-Sl>!C>=oQ%}MQ9iUUpQ!~D5$I#1LoOdE7v);;L5tZpJk z-OXr$=srI$Aw&pX4w`Z^!q9{@NTnlQ=Ce|BeM(jMcvzUB~fPC{UnsKbxE^em0vt4Hf50q3Jcr zK9W=kp@BTp$R4xryt{_oE%ugvR132wV4+Epw2Uw;00Rk&XeAeo~k&(z<5tveib{)suAnZ#pBg;EixrJ55u zQbiWeNSX&lVt~`#6+&)@TsIzXJFjTCMl2YfCez51cq~YKnGAs@y191rS{|Mt8OY#? zKR!Rqie>R6Glb4m>FhL7zB%;aFN!H>RwD3a1{{xEP08n1>#o`NpC z`3iXUx$Y+A^#XP$6kD8qK3zq7w@pXxUf8}La~W? z@SfCH|=9&G_6V4duFn!iM!AW7vCXM$_zV;@2gG~CKkJccF? zWE{g~5Cqh_eW3(;vNR8ZxH!W6KEMhqnFU18Ixu2`8HAZJGCl-Yrukq*yLbQAloJKx|Fk$`Oy7())f>fJRk zw}j=l)tdODT3<2XxR60y1h~`o2Mwv%N9#xyoGSU@AL&h8cHPjB0uDlGC zVQq)TODdKi7<^KGu9XpDwLfVSQ^?skMA#W14EdS0Cy`xnH}QW2jH+#ltt>HS}GMiWvwbV4U_G z9H{BBl35E$J0O$ZJtYo(Cklv+36(V&f$;nEn9wp64J&h7)|h^8sZ|YQvvF~GKY~{k z08i0+=Frtu)ik55kme)bhl8!Da*=i1yiNrU?f?Oxdr{98_uA^$O+MZg4OvQWwr*Rp z7LKaWfImm8Z9wLpBXVz>`2=0|hXf(aLm-1)m$+J^I081UEC=u=-AwQHeZR-!qfgp+ zcegaVXd^!5?t0c(L8%S6F}kI+8o= zRj#Yi3rf1n!rTqJ*~RZ;!(DqtEjwo!?DN@C|YMOEkQeLbn5W^;KhM|?r1c8k}2 zn+>qMN4JPNCQsBFkmb3ID~RkL)f{ECz52BjU?8gwK;@6$Aib~8fo*FxFO!#^6vb4* z?~bjmZmudggZh4~UeiS`Ix>IUM8i#=6Xopc9Ja-VQPYp-lQ{cwKnDB%e*9R`>Vhb> zUc7pHU-jGfP`1(Ii&SR3>*c(1j0mvq$O~txI=A9%&@h7rq!3Vw;o$pwF2gi>k`uFO zieB*B`6h$ogXKPNtyfpJ8L`GpNkgHzwMI6VCeW{l4^&&qXh9>484ucMuD`o!^?~mw zz6Vaj_m#U@56I|qVzgKcR=*GF+1hAJx8OVYTF+HIA%-33w_6b$)o zijql{h#?usL=u><9^7#=g4y(-T(o`Un^xvOJd!z_w6k}1TRFzSQ8`Pg=)A^Vjd;F) zf>)MmJ-A_3Mpc>g8bpZ)=b-vYd=9py%;y7aVNg-x)TYDP2~9Pb7WbG2WhvK=_ST9i z0+^lB3U?Y{AN6EOOFMFROlaU9REknGAQoRd^AMV?tRpkE&Mi9#^@vH8p+Oo7K0{Uk z2CntNyyN;^bt%>46pgw#TI>o8Ss)_QYg?endNG77$3;2Nv00PS7v~rg{V^wdk#XuWUM$O#=Sk@Vw2-?!C_D%Y;eOrcIXv>tRFaS* z0%sdbI<|weil6*`jkGKULEEqBqPTEQOEOtQhnQ@Fa=xfzwrWGt6|Q3Qc*k4|AlmHC zo}@xEISXbv0J9jXAqR?{$t@?u4sD85z{a!1Npp}-SPh-iBKY81Ql!XdpY!-=08O~B zVMw(Ud8bBZL}58)8pi%b#w<1z(}bi&&#C{={c>*hlp0^kK*bAZHB>F~>r zSW*|Eu1gdq3ak@IBp;(|YJ~<$yKx(hC$5kIO7}E9w@fUVtD&cCfF@_xum7_7p4=B!pJq*!j4LW8Q9s-!myQ`%S<2&bI z#Z{pCG#yJ%WA9`SD|RUvV`gw>1RSxuM=u4Qs*EG!94*Y)A#+-U+{#&+D70alV+dh1 zBeQoW0A^;U4uh7u7=K-#+J~vk2h^LcLFS0J4zKmL5jg?u03I7pZk~zd)Tgt@h2$w_ zTv%M%(e%#Q@cEW8&fWY#DN;a(JTzW641ab2dp5Z($pI&(7t@Wjc#fzK-bey?Dg(*zO_-ix&!gLRZTn)TjHt7bj_4N%~D#x1>8M-?%RKB>l+-tqkg&{Q2 zN$kwfRmwfgh(;BO93-@4v!v4kda*>2J607U($2s2a(DU{8VkWuj8v61kX0`Y)c_-IQ%~cfd~PYaWVp zKs_gt{J6Zbn_*1O{o!izh z`O9wIfkabTMy)~;OhLn1+dslVxd*f4=`z$>_w~+=6b1E(?npiF9eaOUZxv*9`8!yY z&KvZoT#`z*8{!bi3POQ2Bl*5Px!D237*Mt8Dt~n-sAR*npkePOw_P0L%C{cofl+qb zZ^44x+K$4&+##OsugoTDyUK0>NxG{wFgE>}a7Og$lo5Eww#Jx?`7L}VpljaY62!qb zIL{1tZ*vGhZ@ALOfDtW#{k0k9ipsAY0%v^|oPij_H~11m4&$%wk|*giqKh~(tD4pB z7r$PDvzv=lhlM6)ACYm%!7{sOnbWQ>5jZCqP|f-pV8g9cAcjQSV${#Zg&3xxDLX+* zZtuWmZ%a3RDn)hi_We5l(k(%tMA@`-%_ zT)5tYayi>HX4_-T1X%%qV_X!ZHHrA0$5WdZl4x8B)c&wN>yVZ6*hL$SzKi^4-^S~q zt~%hBqwT#*V?Q`ebJN(=`AJ$WT}qP>g#5Vm)L~ZG3-vfGZH~yd&r>Qm?SLl%Y;qA) zFYqC=2^k@TgyH_VbQ-!@^j?udK9zx&=;O+#iWw3Hc78)n(%6QK%sEN!mND$4nAO7;N%J4C zZUU*U7kXgiCed7Y{=`+aZs9IHyI;b~IG)@(dJYy6bQrK9dJR1zs|io&)`DdGe|vpt z3sq?0!A+`Eu2{KNip;#XBJacgB>*BqMV^p02P8UxB3*{_qbfQBuQ@!8^%vd5c?jl1JLBe!L zp-41x!yElW%$4cwkZ=A74;;-MoseW8G;_=%0$RxH9EW_m&&`$&((XVo^A3+*RqzIh z7=WBUTFDblM%s2j0Io|UP9;xB5(1g217;#nW_H&;(oq7j!XN1tPeSrkwuBshWsaHw z!W)E^IZxG(Dz~pev;5z*Gm=3dw4Kch60m2eSO|PAA1bLd@A#tx?jUm>P$M+O){6?91Xfq7hcxM4IK)F(%%&OjuOl9yV37eHpJgK zr8%zcVFS)5`Swd^+*7@B2zP_oSgB+;&V)gOMmT)C9cmQlN%-J{`vGCW5ev_`iQqQwFHMgr4eg9{PwFcM z7`mW-Wh(=xt2jqdm0z&YuTwIXFPxqhD(7Bk3IZFy%0?3w5^1Ab`$C=NtsAsMH|7Q@ z+pBmKReK#AGVoL0tk!aaA*80Svx*muZgedxujw@4Z>r9Oou_$P#(YKkt{>UbppB;R^1x@OUAc5$%6?b35Q ze9z{E%9fgJOz}hmAO$L=53SqarHSZ|>~XO{;MAYAxT*=7K-y(G1{7`p=uT2WQW&fV z(WCzE(r?VRjVADDbPiw!Lf%?D@$UJ3DBtt;#a08S3dFf%f(MQ!f+f?GvISFE^UwA^ zNhj}|v1?zk4CHoR%~GRSo`8LG;%niLKd$s_Z9&T3U*V50Z>|6B@CUdT`Xd+U|8e-^ z_v^*~Jp6Gnrtxfr{`Ngy=TFpH8DD(e=pRwR=~>Zp4MUQ@_$p%kuF{9`JEC<;3~Tz{ zX|`O>KT)WlnWX?Ib^YlwRtj4182OfVO_Roz5&~r8_{;YE_9W;2jF) z|7UE`IWvKC1JK^0>HK%WjSxt4m&F^+{2HMZ9%((zlQusp3#_WVR%*1;cYTzj!F5=H zN8?ecd!fwJlC_U?e64ra?}kTyGZm-O@XVp}V9#kOwuREO+AS=k5G}SLC zaST_+TB)5^66hIHel6}ZGwI*?Q{U~Png1@6 zs#iJqJ)lWgW~~WuyOhA8+#~00qwPyX<>nukJ4yVZFj;O1{8yYDya$#4i%!ixM3h`M z;GDfGm#jH%pzRFGeH0R|Fy8=(CT(O)whSW$X2YVqo(en#Txq$=l@;ZOo|Y6c!pv7RU2?B->W2U zpL4qkFz$A(ZA`&~oDn6za zU9_sEO0DRbIYUK9uRq;QRB#ZzoRzfGrXZBEbEF^&AvCZjpqX_Y=uY&vCfqEv+}PH4 z>K_cJGTwTnd1oaYnz~8MLrxJN%e>3UZ8^CdjZeN~g_yn)H_&UaMg2i^z^b&wNMmN4 zdV4WI`)`0}zO-d45j!#2hScuSk}z9LUDM#yN$_t6D~G_$GA}^Z$H-`hZP~K98)9s= zO=|6Hy}^mm;5z``t8Yy`(RQU+Av@0_h>@1Cf;q)tW^_!nREY%-E_v3IRpx?2#<`9O z(rIab%j;%-xNTgBVm(Bl4hvYZ5UF3%*h`ob$3j6Dy00`l%|HSn1P->ED^ePkFfhy{ zH;UdsMGrH{!)yA-Y@xY_Gl$6$lpFXBqUj1fjk7Yihapsa^X6f!-_0$Jq8Jd{9riM& zk4lcQA*iJ)@x7;{PWpO=vB91tllRWN9NPykI=ACN$ckTr=#$~}IGLW;E3kkQVNzmd zA(}ttGjPwmO!~TPw;=$)x=ZmNyN4@Nlxj|+2PQbm4KWGK>zcmi3!T1YILlE(}x&T82eG-M)M@+ zPHrPs0!imu^WS9Nbn=uy5`uJEE4l&qPpbL1bc@l1hET1q< z#}cR`my~Z>EZ7S&=`%cNvQB!{0-F4>sdgAjS{WRI9Zi6^AD?Z>bU)KG1KsXVpG1N+ zUpzV3M<_m)VI~$pUU?r?gj<}17B}N5H!KDkB}6GZkY+*ViM=0bVTHqB7OTq%P*S&q zB@ARp-a0Y|>EmTksF0jt*9FzlKs7uWnu!(Cn#4RY0pbXoIHBJgQ0Y6_+zdj8PdYw5 zR!+Th5`x|tae}&ODe7Y2z(E{xvzUNS4aLWB+5y6o#LWHvtRU#p8k!}R!;j7EQa-ey zZc?md(GE{!1Xax&`8O<$n5{xK{pV*ebLf0}~SMIKbPw z<4g?G#>_D`(vZlc=qjVt2Hf2-F^pyu3uZHyHriOz*9x{KTQ3bGzMXt=32-7Y%`F^d zRIM@T3NRy$#Yzq1060Vmo^9gb4QgH0bQHZ-$iYq*x~`LB!F1(d1?@W?y^SDgnCQ$n zIAl_MJWlswkAy$`rsG^YcNGiTdkv`vHYKRqkDI;GQKJfjO-^S*LCK z_f;w%xwDetn548e|MZFZdw|$gq7-Gb^ZH^*MFWIbo1=H4watu?|AV2cv4XREpjKhU z(x~ru`vovkVl)v^$6w{Vs>-SwRCC#vZDq5bLsIC(XQfViJB}3#)mOJ3-|Rg)QmsK7 z+uEO6Tea7g^FBepF7<7&?(0A%y&8);rtB!GJ*x=TO+(MQl2SUNp-JaI# zN;oa!MLO;!!x5%0sWwu z)Cc?kAcvO=7@(lF*x5chYcDwBG&QHp^DRcRVgN1)K$w(+&>||1PH8X+SEU{o_mLo)%1yc{EfO*Jf zbu~N=;EYVKss~qZ5=r2(K@I6l3Oxxzo9qau@NGI~G9m8{mT10tkY-2r?iLzZyz}Mk z-O78|4aJTRQ}4TFHpeAMl6Y)g!8q*d0%7n{=InlNNPMi3(iI}KVDY3ILW5oxv%%%+ z1n>Qt>6SdDnAcl4ewIJ{)LRp>T8d7U%?IA!Q}lP5$Fk}&gnR*1TP6@>sHO;#$I#^5 z0`wHzob~~Y=pFhZCZqJxn0%M!a?_!xlW z&TzOSkRGtyH9YYNt3YD_C;hl$!p-wt2wJ8pYZIUE#e1OHk39Fl}%HcJyWes_T zrpw31#@^NTq)N%5;RBO_K}<@s1v?o4qw{9ZwKA}{P!IYLE-E?weWzG2RLN*&ctx5R zZ*j@{BJ54;NnvY`iEgh#-!9hdrP(<9V6kQ|TH2HI&LXZ(*=)M}`t61R)K%g{Ip)6I zx#q*mBU9sAF0JJ3x`l5YYRKMyJ@Dp(nMz*U$?K@lB>R-LcL1gl|qf%9RT=^ zFCD&#D#mQp^;vl-oTbSjy#vK|`b~KXnh1`!I;h8Mr0!#2Jl)sDv+mm>dADGQ=QdR~ z^0(Y=IQwrDw@g&10BR{kn665B?W&a;F~zuLFgtKL!NT_sk*){m7Lz$jW<+*tRdI1+ zuR^CXs1ygt99|~b0Oi2M#W{q+API>&uvg@umAWmJfXMBt67YA4;E>ptKL(lgSBd>(-t5ni}T>$q{+HT!uD2xq5ZfD#5N4qh=%nqdWdKHeLD$JCUv;l)zj+*j{ z#Vz0YQw$Wh^364_zm@jM3%6>VpLs{NDP2#rTK4YLPOE_&vw-dpkLZY>>t7x}aiR{f z^>I+`a<;9jcgU&qKGlw;yMFMHiL^1geZFL<++O~g?y9A^vFhM%vQO*4d0k(R!$;C> z4>&*hq3wG^qRv|VmsSef%0mDsR)s12U9|40!T`16XQY(#{Fj@{Qz{!m1I(XXAl`1< zwQlx(Y^SNdB#|=Un6P}Hz1kH64cI1QxGj~ch9CUHmd9Q^!Viu$Tp1#FAY@~QN1V#G zfQ?&hR2Yss4a{lH14TCkuJzcWZAix9;tJW~DjoR5qvVz*GNE2{1aAEdfi!!hvpzCm z{RhEO-^L^vZ?J?W>%>>A?;VORdVyYw7&CtIkN&(|fEb7_$ZP4QizqZfoLqZ3;5Y$e z9Xq<5$bS6Vc1ABFjv$J?U&BygEo@GW@rvX}OWo8sJ(`BFlTne+i`VIXr(sPxT>7(G zPw6$pndsSoZO$LIN8I-RjhGs_9o%A9%nxtg$S;}MeBGCHcj&k9ihg?L!-t1?e16RV zhPDDs2YvpHt>J_0){|LE`I?s>G2kz`U)byu+MK9xOB{t^VT+8)QPNp<-Tsd zz4Aoovp6NB9NgOZ0`bSwH3;BZp-nWrU!=_qmRq{=9leDl>4y$Eu z%&8Sv9U!1SYMYzwWm4{&&4|uEjdS!uuwbq-DBm1X_Ev-OD&hpdXap9Jnzkvpp+vcQ znZRr@{?0%0d*v-8{@q<+XG^&Mw{rvv5UG;7eRCfbM99N^z_&d|2tfZa8^>=gi zLX0bv-sHHOo_lz0w>V(uSoN;eTeheTXCP8p&o;&vxVk0i99+K~o)H`Q?JmX21g^{~ zxozd%eWmC|fLZ3#zU>l;TYHkzsha1$WwU&1kAJP6j!r6ahj)+F3NZi(#+Cf^!B~`Z zsb(0dS6Z^h_-wt>S-zc)%4F$}cOn}u)l7HEyMH@XA#)lrQ#TEu4MaX@+FQ@s$-qMe zaJ&h3&Vy3*w2t2q>784tqU@s5uA?^T;WWtg&+}k1dw~avppWUB3?YDfW+WAPmkL^U zhXAhUzN2(34G&PlE?b!#^Dd1qi)XP2P{*0hZq}V?wor~Notdbb3^U>ArAUQ>X3nsH znM$}HBo<(2Se~hat1sc4u)MA!`ed?%a$%aAk?&~0>kIXXFUZZ>6$o`9WulE5Y(B*Y?jh9ZgD*3ipk?mSh4)%d*0wV(LEO-J8NgG zoWAH3j35<P z9SdTRfpgrhfn1P$mmiw;-g5;%{ULPELX!5n6EmD9iCzKuqju#4W7aos{%90_(gMou zbvrdV2|c%neQTqbC4Rn{$Lz`2K+nng5VY4s?{#Z;bicQ>sI%CLZ> zOrPP&8RuXFh^1&2W3W-Dm!2_uv z9xJV~_vB$ad_~Q42^MMs`DvGNAJzb$l-dzCQGH>ck?!9+E|6@Q@)Yyy2N;u+ID&X` zWMp72E&)r+;LxYr2!vrOI~5B^NvKfrp{=?eKQARn>e};SL4kTXK17nPq~1*M49y(& z>_}_5LdFhv?VN-;LCF*vh3=CeX)T>e930`0Q#lfHAa0M!yA@9%+-{utO%AItX^zBX zPh7j5QAe)hPS(?i6ED}}CBo;ZQbMnMNbIH1y3pRh+-f!Nb=Vc;8Sxs*!$XIu=)(P! zVR^s&Q}UBq$cM)k??Fk;cJeYka?D!~ z59zw2XrWz-yV>M9u=oc2F-w&lgSzBz`K(wG=;e!M;u~>xND3n@V;MMA3-M=c`1UpE zTRQ>2fhWtCNu8VtpA49!uoyW_2A#ctlCek|-59Oy1?>9da88@?xy(Lyn3a)9?S{t2 zS`H3%*G8kbwXzo*C$kD^hC12Mk$l?9)0oSm7dPf-OCDv=D=+k{fu5Tas1~bQ`Hd1t{KOV-v1cYJM(B@kj)Rq zhPTs4sN?OTI!Q+I`~NFs{YS}%gVm-l>m3}vs8Id4L)HLuxstLs6C|>EQfX4 zk$UbnkMHIdSsk`o?SIem{Mh>+*6nxGK+0*LUzI!e;{jGGeBa4e*)mG~Fd6Ip)tVaU ztjy?VGDo!f9#Q(>iEdg)EY!BtFqD^h!BLg_vfZ@gTrXSc)bxOeayF7^gsPZo$Wqz% zY7uMcloRUF|zSdmBIPsU5kCacFD7Z)|saWL{!_n~}|B)Xstk z5J{N0u^E%=66*1CGa9gTJ@UuW<7{)?K%k6o*B4qlY$UTY->xql<`5YkjTo*KD&tD@ zjb6qXjb=p}IWkl+RD&o}rBkv)nArF-Z$?@=JC&(Q=QYi>QtqzuXk{c5ZtBKHZ}#ph zrl&{8_8KreT3J438ez%rHUI#pOHgt=RZ6FcJu|rAq-&|B*Ec3~cC40CI}g{#z`r{n zkXG{3rBL1f$J?2PC7u88{x_utZsC?oTDX^HlKW_-xTL12WiDw-m{a1CHsey7G6AC5 z<}#&emOAc+Sb;j4@)NUcmc}5(aFi_PHzFd|2p9z4^O^tkKj%6R&XaQ z1hRhIWGwm=l|;-L5xqn(p+DVM6rj9)O5bUrmxa!-##l(xmW@zu!0gjbHW#3XfGxt6HA~Nh#AI5XOZ4dO#mMmCnuR)Hgk%B?TA zmcvylSBOW!*Q0N%oGS~1q%*=SZX&i9nvWCbbJqae z6qLTxVnnX)9Bx}=zll|un1>Z8dq89&U7_F&U{zG|KvoHN4o*ntB@prg_w(0R_=O`}npK2=Mu8CuT<&WB?HO zEZCoVP2P%aMQ-pC7a!~I?W>;y9wKmr=VWNx)g1>l?D|`#OOLWdrMYI9!$x+KaZz_+ z@A|bOW|PRPc6Wc$fOj-;qP_9F3_uB=*`|HuJl?EP;Dj zPfuqLur0YEr^?Gum)8J67q`{l%8LZQI|i0xpsz%4NBNG}sy(N^@0{EB{g3-z>8NVB zm8NM8+Qd`eU-L(7wzlP73jxKV9=)7n=HDw0gobQ?e8ut>(ys66iQ5vP$K;G^sE?7Z5mjnkx> zZ(xrNgHtG&PGr>aqweaCJ;v(r#?7+tO#H{(KBrL|KbsmDBHZ8XZ;m-;-xfcs3f1}ZAg(d`D@z;3&uAu`!Jta!%tOE_wBmp6S2K4mP7)Tq%)rjnz#RSKJ|&y zp+(c+pNw9-T7G=a7o$;L;P@#HKY5R8-%&lcbK{FWbuB-moEntR7(bF^QJc{_1fl~S zoM#CilL~=KmPCkA%7wi{GedHv(l_~bu7rE|YQa+IozMC%nEAHe{LsI?8SP;=(eFAP zEf9Toef5st->E+yqUAHD80_SU1C6EBUsSCn7A|MENJ``n8+U~dfU zU>%0j_feG0)ac{!H?O+>`BaqQqvo^6IQ)9W6Wd?!n571b(3&@tgVyvHBog0>4{sl)}LPLM%}a4=msRSQEfS133QBWbkv}j$llk zF8w1Qq7zKymU{S(s(+TX3G-wQyaU+r&fNK%e)j{c0_~%5tcsle>PY6jD;fsQ)tR$x z8ujO%14|dO+-3bT{Eh`F3{slXJ4KFN~6Q5Wyf6X)d0OrFpP4V>OsJ+egnqY)J z$5Q)U6Yx4Uf_3ZA6T}^`_&t`mOv{z>#l=JJ8Mzy>KoNMZ^KW;Ao z94GD0F?%v_Lv9>hsL8x0u%|~--Ij09>-Q70kbji1^gqFguO0J=y4p9?E=rABV#hVX zZwFp}7x>e%z3%eu{{EiSlVm7Rf2WH{3ua{VgXHTscZx|2t5c>92ol|ZL@v3{Fk{~ukIr`wUu4frnCYC-xS$!?lW zU*V>mmkmh`R3A9Pp#k=S7gs*8{-B^xW_W*ykS8C?ll*ahsKlTZ(9dUTIMjj-X)Saf zk+Zm@&(b~XXzA2LUm#v~u?w*B&*5kR7-l*|NE*rqP{vpw!xv>2V4)3Yb666_=Zwf? zin)!$9G+N3=R$l%fK(wDIANJ$yfa^Rv{pfamvSQKtXO%mQUkh=c#R_ws|NTWg11Id zwQrH-)?m371nGgr(zux2vgt1e)<)gx<7k9iLcx#>x&i4pXGJRsjN&$Eo`9EkP@9EH z=7!=$OcpnTI-(l7C4f|iRAL49Ax}c-_8A7v@zjOUJBJ{?Tu#7Z!&H{JWlHRj1y-u` zph3li{-lf&F|$lT!xKh8A)bgZ5~rjd7eb{A`}T(jhPd*vJnU@o@{NCitLAGHp#qA0 zZBm;MvyRmwKuQ`f2B;|f)j}XpEXO|hsJ711qA|;zu|0X#&NCR+Fmt4M>CNR&WmA1i z-$OhbePgJ9{&@2eB?eNJ$%PPY=^CWXAqVnlZ5JSDbSzPI;7Gq`A2SmQuU^*Irq02O&nE;A+d_d6+>Tau>|4ha5{9uW4Bzj zqY+GYfx&CFF&6_b&?GD^Na_gjEBG=cRmm)tZVY5Avgj>LNYxFoRV!EIj{G67 zkgE7Xm7cj16ZA=KnNdxJH4QT_of%~+R-mB@JV6EOoaVVo!gSO{nRoHpsN}OQxPLv~ z4P^+5nNXXYIg$GCL;r4tszynG1Z`qql81QV$FT!n?7cHSZ!eIjzEmo>nN`~Xno zlOV^)?$32ISbHw%LSh;4odO=uPHo#Otb6QaETPp~Zs}>WE@*$P+FgJNb za2`scjT~k((>sEguwo^h%Ii=m;3bN5MFxHzOMvovC78A$Ob;;LE2V-05lz}d;8STU z3L2AfYA3{;K17=*2&D}Y;KP*6=b)vPv1Zs62BhLKznESqVfWQgv&hW(ncjJY*0@#% zq?!#ALn>Cn2#47|j6YOVEY*ipOV5A`8YyKaLMo+P);&VdaoRR|4^_L0x_$nBit7H} z<4-I;#zjq2ZgX>3r`&&|G6q%}D`rtOc#m4zA94Nnd7l{{W3hQSB6c+(9_NUqAPO_x zrNhoK#SpMobx?i5CoVBk$rf@`m|1&VmR{5`ZuIxuocT4sAubc&KD~M(8lUh;3NugO z!DG40_C`i{VDIZ?Kg9Rn?!QkxP(0zlD|pm@yM3aMm4iQdDeuMxZ-hpZVKat6t3jF< z2?PS}^VZg<@{@a4M?jtqbnmEdn8(Loiv>*4pdsQ#c5Gwm8q zI;8E;k4W#Etkm?sS>GnT575)neRg2NGQq@C?oZeo0y`s60piP|n%!1QE$k+;Cqts@ z5;>aVn1jff{TXQT2?J~L6b^>dA0eA*TOliQqxU9va`6MlnHejU%29Xolwx9Mk_V}~3tsh-} zTcI#wBOdN zTIxz@OW%{rXk~?lSyrB!L_M@~B-1I^Vq#($X*fMDd^7d4MRbX6HTdT7{9>u`Xa*KAaP2lM(h~dZg z=t~Ed3{FS+O?F$S7+%rV_&!{O|HaF|r&lw-Junbw*oqDa8OFFDA4Ei5A)D&Epp3!6 z2Sq}+UunFF5JlMxXq=5dmm~lVJVah>pOG9?FA~`wBLu7ro!TK^*chym}Sp;@r2WQcPy^l_HXhBCW#O>~_@9nOUm5|sF9VGH8 zO!>rgT+Au%?Lue>gBGe_9lh;DM|q5Saqz1z9Lw^%A?be4yy0EIX!%AD@yXrFoV1hZ z2BHYYU)88li+Ib2tm5}_!FeM(nX>d^6Qj{#`p~~J-~dK_@_7cLsr#oYa`3BPzUym` zxgU0|VOL&B$K8iffd(*p`b(bW#j?9@KqIsKQuoh4IC;C(78A|OU@oC3#5dVNj}IXP}u<#*hsd?`HGA7+YV zrDpzYT?*!X*0#-Xb2GwNN|{h8^8{2 zL##K*bq=wthI66@PrTlDIjO}f(^M6Cfcw5S(W6URmBV}C?$u{ zH!KXwBF2zcp7`T|4l}NH^<3c4bkRu@xDk5eK9ez0q;2#vF~9Zm;`qxCi>UiX{y4Dw zbPL*5k00&4%_%$hb7(tRVLPu!BN(6a z(kL%OL)kYOpF6E&3W_uXE8qid+4J^=-yV=R%NTNNtd0*7l420vGBj z#ca_v-97u$zRasGm%>7)fD?7BD)|mEXL_p~v)jH+*VMSz6i!(7nU<^V8fAVKC+97*!U625FxBXp4UOZ zf&L&fl_EZ|)pv98J#+hbd5=8Yc1FQ4`Vtp>gN5L_sq6r`NGKM ze_JUyiCB8~G%aOd2n*4TASnJKHhUfWQR{9QKdq z@k39Dqw>rnrEF7@KHXaOQR|veM+GS_z(=7kq@iqe#TVx{^${d!Jvn@*I$N7;k*zY$ z6MZb+Pb_+KH`{xw?Bx@EQ5m5Kw!bz@{lyn!dgCxu-5dhF8~&tqgTGWU&Qff@Y~`t3 zBuF_S&casHOZ>vj{WKL#ZkwT6A1U5b!l?LUP2?eJh28ffK_(-Q>?>}Q+nh`gJhk## z;q?+Bdhl*&<0#};PJ5HvpumxXi@15ozHov#W^ZlY{wBeix=p)d@ zK$>FhLFOUnSwbt6pv6-%T5qEb*QO#{??C;vVAg77&QB8-NZTRxB96Lp!$3NSM`?;Pe&s?))=_d5D+`R5$-@dneeAgt z5Sx{BsG}#Duldw-rdHPW0e|6`;zs36E%`RE{xP!`Mx43cPQipHEsIRRD>A(kubuU=5qGK-7*8z6a+4s)SeCMZzVUO4&1 z<91A?L|nowvcYa*P!JZU$ZWyRGs5^nS{8wAgZEU8W0g-o3zKOCs;!JCRVut)m@?rE?;S}sJ<1uDZQ>jw7tD?h1h8BkRoPef2r~qlJT-i8r?twQ{49yRV%y@_U^h5>>yA4 zo5CC|J@cVFKZ(~a#%+DF)3DzlhjN=-OBoqQgCT7eUp&2#2X`lb7D8e9Rx~Ian0cW$)@?PL!Ie7twti##I zw@zKq<)pl)b8@G0F5o54%qAFfp#!g+(?$8(`dQI)N6lj4AID19KEu^1Qb&&B8byD$ z4a6`5hC4GN&F0+<$e?!e5QWAC=b_WH;|SIvpjq!xs6Bt~PAyr=;?2nM`V$9eyp zfyfM(*EsS}Uk@Muw$Q<{Z|XvL^o|CNiMaG7X=L9>KO=$)r_f01aAXFLHe-+)=*n|Vb zvU+^0-hm=@`0bZuljO;MSc0HS`%n`{vkyN;HUn>ulhAj^0OKaZci_o0lVN@Ju^?>J zCK z{@}uP`NbjmO;9&~bNS;;)P-^=G&Vu2 znBI8;#h~c7PK52@wHv3cp;*_ntWw7Pf8F}YJowKaBM$Z%{gP&ODXZgoB0NNt0dK5* z>FMPDRFv*wc)EO83r|cPtj-+JJGFX0{Qck)9~-yHJxD9PeRBt3E)H6yWBx$WWPOu% zd~mj@YclgV&K(oWZP%=eYW0sHg&RfB)7pnVEYc$!EKsMftS=##8f~?<_SHQ$s=g*+c_RR{*ENz!sL0j3!Xhl;Urkk9^$pW$i&O9tu}64eJD{g%tGJ^>L?A+vuL($ZkRVN_5PS12j_Ow%=T6U$hE#fcv6CL zuO3p<$yz+N=WI$-gJ7UZ(*Nda=I(rWa?oF#i}a)XkefR#&231W+^c5*WCSr;xg?s( zyR@Bb=N8uG9Z`d;IzZp6A(*ecORv^tCl98ExAmGDKeZRD9-QhAnntAUjxg2IA(D5x zS%%JxRkw}jt`T)>+N3&e5<;ZN7tZKg?C3j6>+hMx&=Mm#Qf^%2=L{pu$GgAU7CH{V z7|4xU<>?hA-jk6S)2hg5oj**&o{CjTFx5W5r?@i({y67GPU z)5c0%EreuZ<)i))<}{vG{M~jcM6cORm{(rr0Rz&eK)UwhECFicE5|Qrjn-~Tru+Av za#yVSPW78`vztxuaaaXMb;Mio%(=IkN*LJ!*=*eojX<45krQ8{f$Z5VRSMbIl}7cx zbu5te+IQ_x0x2kN^OQeldvAk!?q|!%mN1nn*q=!)`WC(KptBrOjYpNg;6h8pIA|;< zZ1nSiv%`_)_P}VgYq*%14IEI5PBP^%+E*Y}D)KgteAzKu@)Q+#LBX=V1!0+rqJcK% zI)k}-xVGd^4+o&XEG#<*UKlTt&X?S&g%ri|B1NHAA(Lb!v8O9<^N<^dK~~%|Nj*a{IB+a|7*6S z`~Nqu#eZ`(|L?sPj$~6%R`RGa^=$BDxpmVk?OH41;d7Ip4XWNFe_cj&SbgheoqCjL z?z(jL$Qf7bGgg6@Z&abpt()&zkq!n^qN}`Ke(P%OV*C8^aU$}0bj8t-9_yvcH(;|b zCp%pXUA}d-Lfz0fdxTu*3ZiGVp70Ay!nxED{v{eci+NZGd|OQ$*wU0yNpQaP9#^m>ue7M&r(@R6GcH z#w8m}f@EQ&xL5||(y+7n`Xf^WsB6&xbWhH3!$@k(p=4-)ukzdd!U_YqX!x$1=p4I!-Vr2rWvu$(&tPC1-jmSo|Ep_|wrC7Gq`TY+XM$&3a}@5DrZG6_!o*v`Noz_%l^0zI4<6=yo>95it}4f&3>xOEEW zQT?0WAjXp}Xb%{|CqPl06cMsv{HA4xw(X9FDApp7ayl;3@GKpT&Yigi6>X`Gt)fzT zefs31Zk;Gx6b@GkjM)yC;iyFZA&Xd1b(WCc2j7#HNb z`t<&wzPoDwuFr2II$qk1L)B{_NP9FA(i^n;>)KLnw&0@Sm3L~0U`lB3?z+zc1@1do z+J--D0n2LZz8If6eLw{WBImooz2 z&erdn9_)6has1)c?r-W>SG%p+VWvE^R$jH0x{uLWKYx>LE_E;CTMrP=`R{jq)ErVt zb|Rh++^Xf|cec(U^`+kASo_`c$IP~A9)SftK4pv~>ZKmvqV`&6%X3~ItBKVN#JKur zFq6F|uuQ~9J?_12e^yStlDPK$T5a=YKkQ1*$sKM#FJhw6WHUg+TF)oJ)lASfU_3)) zeAF1qc6w>ixmO*|TYv49eswzoqfe=GLb3|sW&a=>>d+3>`Q?jE99X$QWZ#23iz!aD z5mB38r#-zU#N+B2P0-aAbspie55?1D!S&|Q$F@uY*ItN6`C2{D9${b4E;fS!&uz<& z0sfRv@Y$ByU#<>fvm8U|1~|MO3oU5M8p^UUXsX^BI#ihDk2&bbOHK70$=Zf*uW#1r zSuxA4+SgVjh%4+oKTY4kJDzcvon`lWf0}c5lCv27M`?SRx#z8G>BQ~*PaiGUcV~~x zWwVd6srI7%2E77{s=KP%vDrYHPHMsh^VOmG$-Ox%4UjSQXMb)%=+JzIWQ0B#`QE4X z&_wVkNMtzV5t6CmIYQVF_B=y|4V`xG=&giAts__gtq_dXHp_dw!xnnG)bXk_w3%U$ z?&FVfid8&8K~uJH6KZ{+W7`dVHsPQc)-ZBDV@{B^`^zJUAP@0Ll;njSy?P>q*OziX zZlb3*|D>Kq>gwv zkF^;4uYz!~$sXj`wneuMus|;0_K!eL!VN_JK%LW@!M>>?(aaAdxML9V`?_#@wC(K~ zmn&w-RKL4^{!!Qdx*M?fdHPu(`=af%1=X%3HRRNkyGL+T7nsBUOLDRUp3#`f_rGa0 z)q~HMy&%pM`YzCa`4=g0lp^BOiuu8jFsqU%5KAeJe(vP#9A4K zMU4%5eXr<{zmC9X+9OEK3$b{qS;HUu#vDZgB$K5uyeChPEZT~Vo9@Amh(vAz-y}~% zW_MhN=;1+Mrou@2U~yEyhZfdlSZ>jXeboh7@xeU_3b=B?pe4#_OeTz^b^l8rqdcLIgmx5LRoq|M{_Ir>1O!V?~hB69;lEMW+MWR&pCRjYs+rY@) zECtXo#Nd>yLK%Q~=mSWq?4~~|BPC&l=&Eh47Le=<`huRZLIFu+Pg4fO*~+3YeB2bd zMy#bIY#0^Wt8W}ZqGD%@+fG&f4i=Kk(Pr`tSV&&9ucY9sUa!aq{A>skuFMS-TB040 zOq-58E#4xbn%MWZ>TzIW{yG-Vzzqz$^)-xn*SOdR376M2y5&7so4;h~cWieF>;e4DVV=AUcCfsDoBH1yF^!ee$ zbt+X%J_04FL8@q#94>{>ge>w7bI-o%V)}?o$ro%8Pt35$t(pFQafplr{06LTnpf zMU08-#L6x*CF0)N;(_=~&#~f0V`#oZHMDTsQB^xUQe^j+`GO{UntQZi;XX5?D0Z&% z=w4^EqXkfuXsTSSvQb~ehdx{B{L!DDkH8~qRm%U=p3gKTnBDq+>ADTCdjEwE5$Gjtz$g}VOcibb$&ImzPqiz3j90HF(F(XN_=K(h>9|Y(4 zytQH39IlirQM~yTk5^kovJ*pnp`GX6TC}H-u93D=6bh6#Xn4lX#p%+s2}dqOVxcwuO}cam2pW^`=|Yj#Q9f9u8K0 zCw|Z$Q>)h8L|x(W9+F@m!;`x4l${~omYZlES?Ui9UkKk?tzi&(Fv`;hw^~oGe<%jhd4hD6?BoRGpXG}KJwkK+r zus&~D#;DI&&UehWH-u;68FUU=dPReSbEqf}eb?02Wn)&r7#tth;U4K#1Q1f{zsL4l@4$JM4N2p5z~ zY31Y-IN6s6CoduLFd)G-8Q1;*-mTfs(k>Tt#MWVei7+_)>c0j-YzvH_7V-lzsq^`QFw**KePQCY$BHf2S4Tkvzzx&ys`wk_p8-R~PO6y;UvZtok4`bk(f)?t(1M(P{xv5@+o zxUY$4Pwk^)jIH)I{xGHy{yfIYFg8CuT~jkLAU)354f!)V;u$f1kDX@QzA)_VXU{Ns zQKQ2jk_gcF-HR(%gXYHv^GTeavV#h97MIN}W&`i&az70|%KF;q=hi=?bqXpzd~mEe zc|MSe-#qqDi(vH6)u#%vN`l!%RS%@1Gb9q_z`H?92lyrHCq_=R8H|BBf3$+I0s)}Au0^VcY6 zxvTwFaXIRKZtCezE%qpMZ|2Pw!y71c)9U9Iqkpl$HVaH3nM7@SvfwXM6N|0xE>UM6 zAt&5%%&!GX=!d799X=SA(+^=rXXd& z(^$U6Kmu>?YWn@Fue9KTs-Qsq#eaTs{SE9E$=oqSK$(UCd=imdPv(McA1Ve=O^cRm zSm{Qd*BF@gEAH?Xua;P_xy5%|_q(64xF1S>nRDJCy)il_@cg`gp*7`ALZNlR%K&)y zcAc_NPGAd@W?Mkje_>q+XXlbG1I)-HoZg(_(M9(N61**mab) zS=U7n`;Ro)Q-O1>mr9fd-tc+6W7%FAFy_&#tBqVgZg)JtzI1f^wD(XFuIlu#HTkyk zA*$7yeSTj57fTT*YoK)(qF~{EHMi%pvCrt@Y^aB>33>*i+EWFa5!AsR=2|UQ9B@nY zO@H%6j`JnH za$_1qZDaRwAqWwTA`zq$+oc;1Qx26a4CV}$D%)n!=`={#ri4E4B=hG9O5mF>RfBr@ z%Z?*uGUj_@tu@OF>PzJi^vOJj$^C4J(NgG!oCBf~I{M*@S7TXP zzp|wecswM$kjS4`C{uj%#tCyqhWs-5#;9>}ZG{$S004}ZFJ;~XmBK%khhiS@ZiAM2 zI#8ppPB%p??&T`&p;r}rh4^t$hENqUl5uD&Pf3;#-~gxQ`J_deUokRg`T5>%8e0x= z*uAVm;KPy-#8PgSeeryDRw7`lE2Rqt(rIddV03Mi-%Ws|H5th~`2e4wkPd4*&+$fh z3CZJH0DU4>gz|OzM`VcvNX{*uwFOKYYTE*Xrfsv1k6T6k;0|tq9kaOoCXot!l862b zYZ{Al&gafdi+m11#ijW^y(US04MnG^(ERGp**qHOT=9N;34awe{0N&nd2G5) zoaIEh7w~u^;Ea@|`^#$$YRSZ@Qx+5PNO7byp8n7wk#`19F>>R8`ElU;whXJ=sbZ@VLXBzV&lC~wz8f`x_klOtANTfDnM zKB8xV8U$H2j^J0@%T2%H9EQ_$)C;FKZyr+%YED-fs+oGU z0JPmyem z{j>h9`JJq@3F>O^HY_GyO&s$uad86-@4on6jdLli>Q%%y-+sQT0VkWjy`uZ?QkR{u ze8aufj}YfFzOwzcmb2nleiN3DA-_C;KF?~`LjDx^bF;fD{jBJP^uDHYg6N1x4zp$eOn4%1)jA1AJ`a|@# zvb2{Gb*2$WmF+7*0a}asDep@$)?OW}1 zF;LqFVr`di0JA^Ja!~_u0l%nG7l>GFuZ!&SXK4T<7!E{RyUAl(fGtWYr~jq~C+|)} zMO?WH$OWfKHn7f&k`SV{u!)7d3vZfqRWqI1TNm&ZfXe6~B9T|Nf~_Bb0+4`p4dh64 z!HwU}AcB=%wzH%XX5;e2GK-wz&p~+*-2J}+dquQMDsvsU$@!)#2DbI zonYacV-Ywlt>>h6O#>KiD<;eBDe~86m_vXK5UF(Iz-Q{oN;fkdxA``VH(qZ%um!mC zyZ%5NE`RY6hy{U_y~LJd`1TqOJ>*+}^R(5evfF=DajNn49`X^N0`#_m+}A!WNw8X< zz?|8T2e0?#Up*7(I%KJa(s^y})gRc9Y^3+^{4P1OiM4a0B@*L_Z@QY~c_M6Q$OD#j zS&LVmv900JJvBca#EmcC7!Rb<*^%&N?-rjz`^w&B`_m)+{X@FqmQzcv_POMp+7(_{ zbdwzO*p1u?tTZ~U>sNTxk*4K4$8{?Ub(WE{I7d!Cb=VrE*F=FM=a6dwBVGC~m)Gf} z^W`6MH(X3E1{RE4u`AEN-jk)#O=>wG-CwmY)I9? z^LU5AGxU&GYIw=yo%;D!gG>XpT}`BnarGwP{V#*Rx>~R4Z!(1*!0TOTT`k>3)ES2S z=WGKvHb&m;rqKudj{Bn}_6 ztxziCm6p52Vo8bYX;O*skJRrtP;;tKBBt!I0R9cOn175p;y%oz3pDQRJOioj9Z=E~ z6pwm7NZ1P_#Spb(S0&E*R1Typp#eKFA2f?7a5pWm*ya)+_W8pmTxgBP%WHM;r990> zQ2UhZDQutenX!bT%!Y&|3aA{r8SecQO=y?JDK|drJC-}kM^*Bq;|1ajNIuOxfKrZ# zE~sD7WcnLJh%Wq=aVECfR0^rjUn~HDeVJ-h3$oMx+JME@`ck`VOBoGqIO7!SaP z=4$pW5}J4Hh9IdkXi0(kt$d-f6{z@fHPDlNwnJK_5Q4es#3KhI=C%((^JRcwH;o7N zKuWA^js`Y@%D%Pr@(;=ZFmeGZ5f*~BEBmQs3<#^hPh}0^-=SBWJd99C)F8(vd<`;RpUi?XXbzmf=X(c02iUE%|3WL5Ab8J z`<`C#T~r&=!U{QSf{VgTPeuu>V>4U+@rwt*-$F5c%rNLxx#tBoVNncdM;j0R$pjQn zW$%Wv)uPuNNDB)JiJ)Xii@!0_`lRwZM0V*WhUr_T%$6J~n+KQ-$sz&E#JQ&VRIY@n zCNJDzf@if!Iu3zFX8==WF_%Gjxjl07yVr1yPZsC}W|&g;_{hj#K^!h&QM3_6El|;v zgq2-gAj6|m~}x{b06vvY^@+3kvCr4&R%6C^lCjBi%@nrc|Ox9>sm7ZmBStS2vt zGsox2L3x;Nl;I26+tRbX6;cz&eq&CBfIf%K%6yULMWZX63)&Rl2=g7+YS%`%UyA!! zoG{nch>hk z@;#^Da@kAdLAA3yf$rEL18PUxe4FtOseZZpwQ$FbgbVEk-3>F`VNqh(V~HrwQ28dh zj+&U5GCK?l^nvpjxUCg8u0>?6KEvk!m;l4^}@7$-%Ge?e(x! z+qK3q&fH%YZmSmE-tX^^Z@Pb=hTN=+(KqT`Si19Ye8_|#w! zdUdhctG59h9hQ~=fOHM#_1MM^#95nKQ4P6MZYKUB)Rm@lxg0dvqV%71-_j$r%eO2`em1yEWQCQcdnj{$>~+ZgORl4Txbz&=@e-Rs8n0h=R!Ax|{xBYHnt6vy7_ ze#&@xTww5B5Nh=h z?V7(g)&;dk{m^d_>=N()qu%1513`DK>^@XgKa5LowT^Z(AFw-zzvK}eG}MbxIX!!8 zJ?1hJzM7UA9(7#J<%d_3h~92XUcBGQq>vh)EvY82p1V4N(b*+4%}P7xZqgPo!2K0)v2F5A`P)ap(^f(&B!pSf+SslYgGyDLb1_D^*(zWCNVF`OR! zo6V8;^*(Q|jPWDPNp>WWL4m`%;E)FqhFp|=P70~RoSx0E*zEk}Z>u?-OUZ{4lN>T^ zn9K`bR_{z4h?$sVGXz6fwhcoB#otevF-gHmd2Bfs8l?}>MhfC$s}mrljgkRzC90mI zT&SdHr6c@yQ+r2MdAIiJ&z3G1MX7(R8l6iWj4ju@oh=K)o?0EUPHFt%e$LBktFoml z=VuB}U1`}DR<*C^<@5a3ps%ax0h9ahqHan8uYayy!dG56(5{C_GliXfRA2SPRkPe? z@>okk1kvIos2!S3R5JxpUn|RI!=;iSuY*@$Crmq|JCD3_X*78Jia7$xZSP??p9p%LkoT&HX_mW2xLanOYO0r z-<^5+mG1SsEy$WNjWmbz7l>9jwj$Y=#`m%;%ybZc2IiUn`F2+`QNynfSl1$uR>tK> z7rn0$;Ee>pP~rC~PnXwMk`2Cpt@aM55d}c2FJHR7u|t6KPcy3g+*>~iEax0+x8bj2 z8lWwtKGhW*lF-2I=B?dfg3&+#c^PbP!POAKOtRk6+J)QJeGvn=9<0>C@9Qv`AP`MP z{|8W5zkrC;m_}u|;d+P0S=Ua#GQ`x`)N(t2kigM?*Ln3BP%}xcAVm$pBH;PSKLb$# zP1JD*k1hgFh8WXAx5E;;wJmWde^xPhgSF$T5610_q5Vp;#^s&lX{}XDoZB1wix`au zc@rc1lE1{;54CveXkkXY7#^BiaK7RHPV4w5cm(u}eqKhqK_X}%cYAH$ZfJ?`^k?B| z>2t)69R~2_#@G9BZX3Z_t)a7#u$vaG7VfZ`5mw8dRj=GgYRiG~h}Q?l^DF6LyBdR9 zP70HEjZhYhUIxs&A#(S5XXFo9AEM4f|nyegMFEJ9D^&AEib z`>sB?q_-drv6Ie*Bl)fC=z*Nc2-smU2b@dPHhOhUwbY!JK2PN%3Y%VC@RvxUz%r?#lZg?BUFJBq=X!6XynPsLXH~o9=@%T&Y1sP3z2DMpL6b z#4gNgH}0K-vscDS6Cw+w%rzzcpq&Dr+|d3JLV>PS8oOkk+o32HtcV12Li&SUGC)hI z&Ig_=0s*4s_K1W9D*s^#e}k3H7%JXxyuswOZuToiN=Dq2qJlLjqE@D4V8j{hQ^7Q> zNHIp88IbP9Hjf(>I~R_G+sY(dbkCGW_4X=+HCLNtKaYU$M28d@1O4(jw13C^nY63iJ=>GjJijAhclLyiK4>5OXh zAbCG77vfrR7L9Qn zsWQ-hfe%*GkO~rTt+>FN0ru1CB2lb{rIfakvUOCLe&}TF;tXd=uI8k0G>S1C;ILId zYGi*W_$tkE7=s+KGbq5yzJORKu@92aQ&l4HT66Peop~7NrK)~`YB)vqFm(#tM}jo0 zj5s=d(Kt~|5YeTY0*xkP8oV_}bxpM zZmvouTC9SWsw~nc>J=PoM2dzpn$@?+QE?VHtZ_)RPOhjkR&a=F(h}4My?bL<@!e87 zttlP|?;?_peesZd_MF+$29bVk1(!5&QZq-+Bup^X70y(MzQnNr*QV<$MYd4fqy1AP zX)F8t)lKu|n)*b5D}VKu*3iIbEv015CJBo&4SE{qdZx#=P` z=lC9yAQ1|JlFNPQ9l}M4Xx#2|kbbUvAQQqwPkSrXSxn6g@N20VER9_2+%!=x0zVyt zi{MHF(Pg(e#H7GCU@#!pvlYk%x$5!MWShR{;5!h)lA8M=)&MJ2)5qbY%IR{P5E>8& zLtBO2inzL@N!&QIk2BlFqR&ld4nRv~SjOEdj86v8eu)MFH+xZ}8lS{Flky;Zs$hC5 zHe1DcJPGA8s!!Zh3#Ra?G6wr7fi&J-sb`B#emWAX#37#!B{*^ig^_prs(QFlASyd) zn;l7BQl&E0d$wlPYQ{e{Hlz#?9z@dP?#Dfd?Fkx4Qel{^oMpV-#DbFO+{q$Qbpmoi zZhkK{!!EJu-&AKDrVcLcp&~q4L^oniQPN1%H=>k2Lco)zFz&mb_8SxWDulsi7g zqYwEX*VUYoda^>K86Wsqy55Bo`Ly~TJaM<-ePL`#ai-C$R8~+@zh=Y@m(;mAZ3quW z^Rdz-gQN`n_D`8j7D7y`9^8&U?`o`P$7AB-gjl;8P)81F;$wSiGIhKOJHN%8e!|Yl z<`Sd~Bc0)JKDL>w*ZeKW;%4WMjr)jreB?n#R-h*#R++`5)e`)=Xzq@l&D={i{Ic$C zB_#>SnHv7dN}T~6ZSIiv$nGP0NHY5I5p(ciB6@0q?JcK~e0bzjE@ojHtrF%TjNf6y zhk12=EYQtTF(&0faSBtepsrG*2lZteV|IAM=KyuCfhpjF%)wx zzLpT?ItSRgwN}x1*U>DB3Bj8+%)`Hf%~exsh+%jyLT3y%ZhY^!HUiaNNHwxFcT2MT zv9`dp0vM29q(B-GmP9Q}rW9;ltHU_kmAJ+xH2A!EcolS|O9(WBK6-WmQJ zy(FA>9YeKu(P}_bBiTNQV(O^_zO@yT{ZHeS@49kces=ZvSxunWAS7Hp(UW+2HyGAnCV1bmYT+ zSZ+W=*$Gp2Iwe2wUL%5QZ9+vPouHgE*cje0D-C<+E@H0t4Z7 z1&so?Koq9#h8-)ZC*09b>p;xv;;a5H|N3=QzxL{(m&tk?pC2w>8GU*6U+t|IiSU=m zw=OU2Z9?zH-BuiM-hh` zybxIqCB@a-2?Yhy1r+{jEdGyfy-2l>+#e+E;;JtQzGr307RibGx#(3^ld0L>ChoWL zha|Z`y_aCIeoN-fQJ>73b(KNCaZ`s+{~CPySDhDsk&k}L+hOnGb1KqH)jl1uTYC7J zU?d`9L691)%&U?}A<1||MyR}Fjwi=;#6U_R=kw>&9lPFMeI6Y>h}D%}y0*J3zUIiI zd*8YY`;uJfZhyY>Y>vgTUs@=&u?7z7zc!-w{eA}h=l#!Q%aV-vuSmX+!1Kj9Bimno z15m!hc5XH!hwgm^NJW z#v!3}YPEVgyLooHjPBn>D?anP_RKqDeq@*73tJ*M5|hWZhXHvnblQluZ+MqU{I5-6 zn!1@W`vzXHN5xC)z&kD*rUFYh+qY)LTQ?h}PoiQ~^cD@+1AYE`)IfKb>i;q{EWXY6 zdJsn36aSw~-_k){O#jfZRe&8YD~Gb|6}nK_Y+*#UB{<~v9ZYud;F5ygyN-Kdnb=$b zg`qJbL}RG|g(`+hP!4DqYCm80s^(4b%b?x^Qo-u-^OZR*t@!48z-{0thQsHU7Vqw9 z2FH&LkK}`rm=q9;qtg^3er&4~TTKBfa#2GF9g1VmK~UdVOQv9&(1BGhNCek45&=gI zU3yxN%~9)%JvhK+saE3TGAK5$Uvz4PBL`wU;;TZOjfrU-Hum+|(|JPwK4H#i*0V=|R2^s8csYD`iOs#(x-qUic#*D7MH2hk@( zF5<@EomH_Vj6U)CF5G)Rs*VJoY&idnp#GEpKKa>w-$8B)G5UUNCQF{Pq2*onICZT` zTXzd#Mi`X~m;&o~lQKp%wa&dCZkRqo0J&HG$?D~Y)S6Db*U})QT}Sz7)-&a_G!|Er zmA(n%dA(%8-C|fr7{&|!Pq91y%2oR?UeT<3ZRg3JYBbnET2j>7b%z<^2EtQ~m01SC z-}Alw)4JvwJZLb|-lEFT!enH%-ExR$BIsj0E6I*rk9rVZ8ytoljwa0Nmi1I0ti@_= zv7EN+$0ggDk)x9Oe7R}0CfGHJjqcUWllVQ_wY}>vU?*t~navIWJcwv7E9>D$nqb{) zgQ;t%8(bU%_u~J@>u*cRsMRSQ_Y|`fA`-`-9#4sRv)2AIk=M5CF!| z0c;Y>!hJ*DzSgKe$`Gj1zk0~95=-rr;%nLm@a8ZRFmd1#3ZD4ETH{ZFR0FKGHNU_+ zCT6wccrch<7#M(|>krLK*G-D`ty$P_38x&Lod!AH#u0!2?xz3pVwb~pen><0zPXNx z+rSn~UK?GI;J^P^L}Qs*?-lpA7d~sZ9{Qd%(NZ?PvBl+;rFq5Y_cU+V>$&s7z~V2B z1@Z3^VY_-7VWxEz{#eAJx)zWC$vk(Owz{AR<8e-)lEwnqAIdh7dcU-0~maDYU__`zJxAcHM|CdSRgxfRKV{qoBss)YUC z4Dr?w6WJWRFCrq?UQPN^`=#A!Du!)LaH{!IyBJJbb}`(Kp{L*Rr0T*cnQe9I^I^r+ zvnyU9QBJP)`dIC1sZB8TOh-E<|9%oNOo1cfQO)iM6jg_|!NpI@%yMMR&gik#=FeX+ z!{{cR8-UfJr+vl>@rrAD6+zVjYX{J;0CT#?w@7*F{Iyj-0SBy|5$qSE;u{noE!8dr zfJ0*;fd(TKY}}Y%qlaoMdI2~e4bMR@gKDJZh&k85g}*X^nO38!E#W`-hjp#B2rJ9s zePH0%1P?}mSS-4m4D@n<=Y#j14S(g&@1g8ra8DFAnXS42&MSJbJhGOfZvx79jI^;n zc852h37Pe0U)W9%)4{sjko`Oke4Ha(J-2Y+szc!2VA1-)+Y`XhQW+|B9gjg%_PBpE zO9ZZ;0=VV*L%JQdL>PfId&Ix#8-a2lJ!p%VHh1|StieELmj`%qP!6Q**z#uUXh_rX zspcT^uyrlA%TB5_ZZQ022ax;(?XU?l3EpvY+;Fb-xjx_tcJP~a=L}w+j+ZiOxc(1% z9YA>`4kOn7oW@75NsDhqYg=5#<&}GPHcNpiR)v<6#pwmTMA4H`{C;;nV0{H z8mEqCBj1xF%KC>E$@o^l1+22tt{fP>UHNoWO{DtI^`rNUWp*Dl_e90Mujdh)>;0P& zToEZ{A?8L(`>Wm&vprvKvet?BSVawMRpJ{TIgF(vh^w17rT1KN@7_e2F*VxKyZ~4y zLoVSBwLzF+tAT7ZurMgr#H_1Kd24@AFrecOH;gnj)a|JusT$JnBC^0I@hz>+J~QAt z0|>r-JmRwyBN7`DV5d^t#NfWh=C`(r(iydQ51c$5 z?2ZRQMIn_F^not#P&(10U&T*)e`MYGH-&~JhQK&T2~qbDAheH27BVPWbjwn9dBw&J zXgCoB`2}%I7;}LsjB3R}z@gJm7txtX9F~9-G*^!c7RKE*%8tU3R1!8xQ#63wZz)eA%0>NiH1yyTXQe!2ar^YoB)&crp%$k2l@5aS z_hbg7&tv20oWWY9W?ZUhDJ5q}RT^V;HcnYSv@d$?03I>)sI6duBfk)e(}j+g{Q-Zz zieueNxvRTU)D!ib(!vondDxho_r*B#L_m48v`NKZDHF8LG;A z8AOO1fN-S#m;9*=H3Xy{AhpoaT7*9g5&(;wMK(z*JPYb`t&j|ZV_^3tNHZu)O@%VV zg=&#%i%7%?Qp|}|5Y)f{hsFC}206d1F~hY&RArEiPCBRTH3t!Z{&)JJ3bk~;XhtA{ z;l!(CLO|h%&DOy5U1!CE%{AFiw60@K81<0ZD3OBI~O9!zT(u^ce07WpRnG;fHB1xu*$sL?NmlLTOpYCC?a1fE6 zLov@G;FNM9maYnRn_7~9*&s6`Mcp4I=Ln=xS+O#rb3~q|D@!&Rlba-q7D;o0lAR@R zhsge}77pCD&oCn!)H&yE_3WTjjby5mIoPlC-{-y5XUG6U+66&O_bVJ6Fk)f_i*x<$ zOjcAUAv11y{@D{VkQ?6_(}3$iMO&6FOQZ0VFbGAdP6qYvCQ_`T*y!fzXE z4^3qn;VFG}fEP&gdH}puq|8aQwDm#Edd2{LYd3Pv>|B)k!ST%dMWhY6JF&_h?z+iN z2HUOoj#uL7@#yGFds1oJdMc!@ed5W3OS}+oUD`$ybkDdu4|F&}oIXx+@jYee!ag&! zJ2%6aGIs7LInG&!9(CM&3Xc4^;M_dz-u`zFIM7>2EbDRp21gQiwh{xpJCe`AJ&{6~djSz3F8E-;_MsL;ClD7u*P^xOj{v=v zdkqz4W2V$UTn3i&jfhHjYhP}$or_uVAngvD!hF*4_}Otq?6-!LU&S+W|47a{w?< zB8owUJJ?9e%H8*XcEG=CLiNH>WM46LU&*#jw1A$v`>r3jOGay}gYDiK{^UAgM(m=P z1m8LS!+C)2q8&Ivaos-^@*NmY}QY zM$j)ufcoo8#O?RPH}2fC)&~F(O2Ca@A}qCwpISS9;GW&61xHZB{xS>rrI-ryN0q+% z`%xpTxWpL~Tn*yWez5-V{k{pzaF5~==*CcV@Q$NrM@FK#w^C{AnFV9`bGOD0Uw8a1 z!t}Jmp%$+TwH-0k31&2{cK{R&e6t$f0=}Zh1KnPfVx~jt2v9;a%e+HldbSX zR70b0N1=#L>!=Rps}=tb4h4u~ppZX+6P`O={}1PftLuL!nc?yOEt&D-v;J=-Gwk@L zlVyIrhik`fioC6QUb#DV#iF1^@TxL*JAgyLx^@xrAA!m=s>5cq4Z8=9gR6 z%^je8Sl*MiPV;U) zv}+-n*L)y*?;AyS9LCfcys-cQaKwjz${kH^$8;TtFqOUf$E_rY@f_j5Z`2Y4JHHNO5fCnB*2Mt< zo`_|xcCpQ{oYtxQ=oJ1zL`i)&~%rrsYSZ$kM@GmMJZIC;w?f1iujhOsx=s%?< zG{mFW7}zm1s6D{&F8=8-zjgV4-M)XM8*wK8C)ejk+)??BH&DeGGHjQN7FTbVCl&Dp zzXtrCK>jB_^TH3+X?{V&8~w5$Hx^i-ujh8~8^;p9j3R^BK@A-FyLJuOr2uRqcq!o4 zX8H@|jn<#QAdaf16;=?u8PZ)lDQ1A^1!{XBN={pkRPP4=z@|>(T|X2y(hv#cf6#^R z!B-$*J6?Nju_vfvgw<$QZ?z=+!9|`Z9HD#|quvEmKj1ldnxU5>>6gm%|(Pq^z&29@Mf8FTj{EchC~lM zaHa$_?oPb?-g|mYy91%=nE!oB`sFj2Sz5WnCFFF|p{TM_A>NO&Nl$v1s5R48y18_d z)f-xW0~tJHF6SQFDj)!(3gy7Mg;4V&A(#Cs`;#5~Q)bp*H(!%}aN6~9X_TMklTk5k z3iIyg%^SqpQ@}N6`r*0|+u1z-sr-u5!Kn~lh#5w(ZlO33yr*A7#O{@_!|CL#=9w<4 zFI#I9W_DF-UuCbeiqB0OWdlEj5Np^UcvF-^`{F$Yc5Y=4(C%YXS{cfU zRh<|ut;n5SqnI}}X7c%5A`hd?gn5MYhqmFz1@J4cTy{8Q^Z`J7+-McJbnVfa-1E@I z?l3Ve{cipwAgI_4TkafM(_Np~WlvFi0XER0YFzE1UIuQdW&W(VXKbNAJ9Kf{eHv@3I1c4XCSKK5bhP#9R6+@D|^$|d7mcdj+g-P%hMP)>~@l4>RP?1QXhLpxiaI-W1+V!bF zM?qJ&L`QL+uQSsur-!eGj$1i^>VKg5fg)%@1c9u9+DS>DB~5jM%N$?!3Bp6TOoqY6 zz4yIVJV2pe5!(-`+0GZ&S2OgW!29u$Tw^@}sX{YDCf&T>THLuuqQ%VW4f#iCLzkSixR zQ~@--@nh$ThpfLvt;pGsrS@65v_stea`S7ZIImAMrP(5rr$8JPl=vpa2U_UNlX5uo zMG`tRo~5co$rLL`T2w`vQaqb9|Apg4w-iarBx+eteev}mI%Ema<9+sML$YC#OzkF$ z-{bCn-ym$1q>jHVfh?aQWqcLAABs`_6{E641a; z1+eOl&+x@lmQ$_ZF859}z@SkTIib*TBY1b&OvXWjCJ_onpRt@V5EILs_gJE9IDJ)YQrM7v zN6!t{0S!+sXR4q`LFde3pZEeHPl(Ha@Py7dy*NpfOs>+^bC{*$ZMwVc;I?^{kq=_! zi?agYa$ho>rH`jZ)`}p)8Js4kI;pjoj^IIIFquwc^9fPUH7~WOTWj5!|Z}?{Ecx zC7PjB+y8vZtr|6j|3GIqNQ<{OaA*8;Be{fQhCgYS7HDrkwNuReQ(&mNHtedkST3IE zs|N^-G=rMc_P%2YCg__-?GwPM0(RBPE754}?IM6KK#tD;AS>VCg#n1CmUYEZ|MNS! z@zMDpa^MDtJ0|{K010h-@oiMYkTxuUc8&|upMSQy^mP4fg-Ad(?pl{$UiH7y5XE?- zMr}k-4M3@*{%6`?thlGS=bkqTRs4keLu_9SZY2H2AhH?2E-U`j_+uG@ZUllP^MZR; z?_XZ^_dja&8okavdLKD1CefdRTd6tCQ;}RYJMZ{#WySU>NJDXY$JUo+8o|71mfGaQ zk0|60?U=G2GMU|Rof`7-B?WE_%#6iDci#Q7Z|`(iKV|2w>fWorjlbO5VKS=c=Cbwh zs-HigZ_FeAs7@?M+~C>aZ1%EWJwD6JYP~U9zyb$U0wEisQ2NvgMVDCuwq|y zcp)D-@9TXm0AA_xe(RO@Kzo2ma*eIz{jY}j#-fT#|>XAQpBi%?uRf~$w{BX30lMp>I_ zy3Xy-nFy5s*4tZp{4MGR&G0s6XGf7=!6_cZmwjJRo`Q%Cz~*XIqtN#YVo|}!F;Ik# zhoSBwGB@n{NLvewBd>;mU^4!QSPX1Ib|5%m0pr>pnh)_SW%; zf6C`i3AZjV-ZA!Bd`O3H`(Q{E}J^ALZ(sW=41Qb-HyTvLuMNm zr}(`aEz8Z1$F&)H(C|Nq6o2K7iT{!ZlHTrNLfa9 zSvdu)E~o+Lfs>=TzB9ob#FgVWyBK+em~ME!&#o?}n{M@IZGy}EWr}?kkC!$Iq|_}r z%kG-SnToX0(i-sodJP2l@@yuyi}!<}>U2xLXbOJiW+u#itXaiRM&#Nlga_Ykb`&%l zv!|LDA#g__wqPH2W-3|;NnjHcv{a4N?obP+TQhZJ*&91#QLN_0Wde=K=^#>65>;QN zv?EfYBeb}C$6HsJI~Gz&?;a!KA*V2-sOMjgX3!6Ia`+QL?7R%d^ax ziQ)t4s%KLT6+DOqC2=C=YID7F?msn(kT3*M%dQ|0feS5GN1Dh)pXAD=J_&A#%~Pmy zwQ*~u>dtY2vNIJ+5=?L!p7lqWK-UG!r-E8Oik=M|oGaRddv@w1B}efr*!ioUn52ZD zHUcS+BMg074}DX~n3$O+pXKom==w^8ngsQ2iFNO&j~-+aY;Lv3RZSMM6zZdCbA!yM zbUK1FHOPUI_X<{=2~Uh;I1nVsRz*P3hyjsifTR%nMD;&kweIdClfO3qCTic|5R=G? zNU4i#03Mv6VD~v_Hc{RSU)O_+Qj7c_f7MmsRqE!zElk}-a4Ht!aur+%@99WCe5woV zS5#^$gaxY**#5qi6bnQ+JG&_$do`oE@VUtn-_D@l&RXz%ed>2x1ShUuW33TE{hETA zdN6$_MaXT|RXxAiGdOb(qC>a^At~7>l%aM`#Sn6Ei~AK~k$_mF7SX4d{i8xPKW6N} z_G9HB76EgfWC|P><**W;se_OJ>hj^^Au6Ph5@}|LdI3uTbC!q7;O<-0IoVJHT^5@G z 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

f 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 oqUz9ddySh?;>n`ZzApP!}vNH zYMC3~d*T5NW_rnX0rWJieD-kD^g3tOWL^h4%;4e%ch2*M}rSz<( zNq6(~1{XSSisliLZ4m>ksdl+2YZ^7~RF z@$H5DF*y>5;Ku>kXE_~RptBCDQBcO?_?RO>%YZ;C!T*0uy$w9m`~Uxc`<&x287AZ^ zxhg7!T;)({Od`g~RfkwB$;ef?DB}Ie<|0Z-8SA_`dnV~7XWlb z=dwlHY}9z3O9?s4rf*n#kvUYME3(A)icvexyrk);weWZeg(qj0(!$gp7r|25TKvt> zvPJnNoVdMQPpWvl4_+`)*5^$hau+PU0WG~uy)R>x39qp_G)>MFd9oFYRV#gsE=N~$ z*P-IlSJD{(yI_yQU!TBYi99R24H!08`f_+HJP1%I!-X)2>+Pq>vLc?yz}_4hV@m*F z8YdE|=fOaBK*$7cM};=T<+E2gb}(Gp2cqK=*sN^lcIlL-X84psPXOcQ*=)tbI}nB3 z_w&|Y`>cp^I#ARA7Y9biL)P+H?pSIom+xG!gj z|6s{vll@VU^an*s_L?~*D&?H^ngy4!o1Y~-RRZ?Vwl3{|H!8#RMIzj9H!|dho|!+P zSHFCz`@2jrx<0Mgf_VIw>)*vnVHb;2_5RX^MX*UT%$pEPWQPRuu(#_bjy}Xx+G-5- zqC0%iT^_N{^fNp_|9H?1>Y+xpSJ^I@I0k%KHE|FN#?<6;n*n*|s)^tjIqaP~pUx4B z75#K5k}gol`#KabB^+*!AC+}*`s!gJcZCkYR5%N?!D)&7?51e&+X{;elVxXt9mXmh zxJO6f?o1j-Ae9KDoKQV(A{EP`jwu%9z*`}u!B{pWl9nZD4P_V5 zjx#qH8ji+;hX$>?Zy~C+wcN*KD<4^{I9>~Z&9Fik z7WAy1X>kL4@R8A9$&c!X9`s~Oq{xs2C-Z|Hx(Ti_s)8wbYE4;vTw<2z?~82pGuvs$ zNM<5xRgeI~t%bmo3{mf0x1df{sUwCN_{|$n>^#gGHq1K#JpzbuRd09w1|-gABy~i7_P>-P=ln)a74qwU zC4E>id-%`Y`u}_TUv$F%ZtcZu|NqyDHty9H0A26|ZuZq?Z5k+wrv{GTk=}c9FGm{{ zEjHgmo<-kH;cEHZdZ6?!+G7B(yJN@m6Oq9G)Kb^_5Y6p#>w!k|;|<#J0|h+;=aLFE zkmc`C*;|$>tUvE}46Tw6NJD-zuG=i_SiG+=S}8wF6mfTJ#RrI`tRDLGBkE$uz5PT* z5Bv8Vx^O?dDf%pwIZJA%4?nB^vGSL8vs}Y1DEkWz_6uX)$d|Vb{yuchT>tOD--;3{ ztH7N$=CqT+FNb2x3rDVNA%8{o#~wBQ6YW+_0DK}vpyPTq7`DJ0g1he4$bKa`&&|+EINJ6+z&n0a6&`e)HOQornqgh|w z+Oo>;<3RlFUDaek<723WCLv2_-|(83>f~%`*U{{g)s#4J2u4~ROKeY5_^(%kqlzi) z=$Yp#*V@n_A1WM`-`62oHDXbEKGsU}nrBAX=NovVV*XSf?kjyDGQnCBzKUp-O_#w# zHST08Pj{+xkU~6(2CKa{fQ)i;+FM(U|L&`iAga438)E(V2is^J^h_|ENMF$M9AmbM zVF9@yN(Oc4jnQ}tI`|Min$`H`Aub+RR%YLT4^Q5!ZW}5FOF$b6$Xc^-tmUsHZT6+OVLdjt~e|g_=WwYyDbXa`?nX&=0T3fxX?M6 zCWV;q^v3w{{DO-Zm?~|P!eTZK*ViQn+epbM9Hmgu=n**aN*|S%kh%UICOCKBRdjT; zOSw*Yqn&-tP#mYnzdb&_MK3&RR5m7#B($Is9!KV>l8lhs0TYyT3-EJ2Rb{cxyYe?5 z7J8g_Y$R_te502-a(HMeVY?j>%=CcG*OY5o73sLj@P87X&`f(0N#+Je4es&i-d)kM zi}X1(e=s|;eS%<`B^@UX5jotV%yfEm*rL#p9sIF^|A%X={ZIF|utLXVn<_{vAAw5r zV}-dZ()6rauGSV3#t~G{!>93%_8=EJ(C%uk79LT&i_xHAZt$BvP(gUy0`swrM+z98 zrEGZ>{}(l|Q$;J{0Yq_PXlu*8Dwsl$#D}d|oM6WT)p*X$wMD=2pDkffb9fnxYKB$*W6OEi~8gK<|!I{<E#Escp^0*IziMlo_EWdi#o>sIR<0GK zQ8qMP_AL4-Kh;QPKA4-Cpu}tL5)a*Mo!51P!i36l+g4sH#b>cEH#4%;N18#oZJY*4 z8QIT5#PGa48({slCuCGMCHqQs2dwCWN0US=R4J$(6l$!l~8fN#R$0Nen4Y~9lYQh;g#2AQ>rRabZdL>0;@3OIiYUAW-b zlXcP-M;GDX98S+MnB4};AeodRkiuVS^oen}HP{P+)^CR1h2>X5L8&L}=4(>{z{K)? z&ofL04CDrKwrH#>oc4oQx`Yt&aUjyFjVlKZ= zy7G4|RQ8~<8sr9yj`FBd!VVdHC^4q*-66W;F_}E99gbQREF8LKCH~e($xfmKTxEy!m&p>+BH%8{tVtv#y@wm#nqIa6jp~|E-HmrjNK<9mVI4tS@YIu^ z&~8U9wF^LgkUnrrrEf87sY#v){=x_x1#5f_eIMoVz-qj8`vw4YybJs-hl1;(BH{E_ zr|YK7>mZ&41=J2$lwJOu^R9v}+1AM1WAWe?Sk%Qx_#wd*lvH)Et97ag&R=B&*%OJ* zSAQGE$|^-7bQ33}M8HCO3q^-@9Q|%Q-VH^IJ}P7Pn!l-ML?`PkRs^8iK-!SK%aOWU z4?vVJ@O+@~AZF>;ttDE~hGv*E-GN`OA?yow|2waqW$0qr{5>MvtnxcBG%y3+Ai&)~ z{r(dfQP>G&24G#Fg+$qretrW=p`RyeFyWhPmCrka#5EFF5r7Pz|9g17Z~UjA0b>W9 z>d&j?6fBMJb>gAG&jyr6jTW=YMUVU|VmyyvZ=A_9eOwiH|Ja+ezwk`SiG(@7VP5kM~iYyd5Vj<1vmYKaZNHc83-MQ(DDg@Wl%Q%meK(X32QeALEDL zeIXt=l6zY@##Y;Of3(T+zXIdUgjzFHHxGhk$eq3N&YZ%6DpKuYH7C1Q8IGgbyZGk

  • %N^@ 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�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 ZfgD{yfZwp}%*~mhV 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 YP6VVd@bHcTe-!BP@XoUV2_n4z0d18xtpET3 literal 0 HcmV?d00001 diff --git a/src/modules/oldLibrary/Material/soil.inc b/src/modules/oldLibrary/Material/soil.inc new file mode 100644 index 000000000..50dbbaccd --- /dev/null +++ b/src/modules/oldLibrary/Material/soil.inc @@ -0,0 +1,189 @@ +TYPE, EXTENDS( Material_ ) :: Soil_ + + !! soil state; frozen and unfrozen + INTEGER( I4B ) :: Frozen=STATE_FROZEN + INTEGER( I4B ) :: Unfrozen=STATE_UNFROZEN + INTEGER( I4B ) :: State = STATE_UNFROZEN + + !! soil type; fine-grained, coarse-grained, peat + INTEGER( I4B ) :: SoilType = SOIL_COARSE_GRAINED + INTEGER( I4B ) :: FineGrained = SOIL_FINE_GRAINED + INTEGER( I4B ) :: CoarseGrained = SOIL_COARSE_GRAINED + INTEGER( I4B ) :: Peat = SOIL_PEAT + + !! grain size distribution + REAL( DFP ) :: Gravel = 0.0_DFP + REAL( DFP ) :: Sand = 0.0_DFP + REAL( DFP ) :: Silt = 0.0_DFP + REAL( DFP ) :: Clay = 0.0_DFP + REAL( DFP ) :: OrganicMatter = 0.0_DFP + + !! index properties + REAL( DFP ) :: SpecificGravity = 0.0_DFP + REAL( DFP ) :: DryDensity = 0.0_DFP + REAL( DFP ) :: Gravimetric_Moisture = 0.0_DFP + REAL( DFP ) :: Porosity = 0.0_DFP + REAL( DFP ) :: voidRatio = 0.0_DFP + REAL( DFP ) :: volFrac_solid = 0.0_DFP + REAL( DFP ) :: volFrac_water = 0.0_DFP + REAL( DFP ) :: volFrac_ice = 0.0_DFP + REAL( DFP ) :: volFrac_air = 0.0_DFP + + !! mineral composition + REAL( DFP ) :: Minerals( MAX_NUM_MINERALS ) = 0.0_DFP + INTEGER( I4B ) :: Quartz = Mineral_Quartz + + !! thermal conductivity model + INTEGER( I4B ) :: ThermCond_Model = Constant_ThermCond + INTEGER( I4B ) :: UserThermCond = User_ThermCond + INTEGER( I4B ) :: JohansenThermCond = Johansen_ThermCond + INTEGER( I4B ) :: ConstantThermCond = Constant_ThermCond + CLASS( ThermCondModel_ ), POINTER :: thermCondModel => NULL() + + !! volumetric heat capacity model + INTEGER( I4B ) :: volHeatCap_Model = Constant_volHeatCap + INTEGER( I4B ) :: UserVolHeatCap = User_volHeatCap + INTEGER( I4B ) :: ConstantVolHeatCap = Constant_volHeatCap + INTEGER( I4B ) :: mixVolHeatCap = Mix_VolHeatCap + CLASS( volHeatCapModel_ ), POINTER :: volHeatCapModel => NULL() + + !! volumetric heat capacity model + INTEGER( I4B ) :: SFCC_Model = Exp_SFCC + INTEGER( I4B ) :: UserSFCC = User_SFCC + INTEGER( I4B ) :: ExpSFCC = Exp_SFCC + CLASS( SFCCModel_ ), POINTER :: SFCCModel => NULL() + + !! Consolidation characteristics + !! Hydraulic characteristics + !! Undrained characteristics + !! Drained characteristics +END TYPE Soil_ + +PUBLIC :: Soil_ + +TYPE( Soil_ ), PUBLIC, PARAMETER :: TypeSoil = Soil_() + +!---------------------------------------------------------------------------- +! Display@Soil +!---------------------------------------------------------------------------- + +INTERFACE +MODULE SUBROUTINE soil_display( Obj, msg, unitNo ) + CLASS( Soil_ ), INTENT( IN ) :: Obj + CHARACTER( LEN = * ), INTENT( IN ) :: msg + INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: unitNo +END SUBROUTINE soil_display +END INTERFACE + +INTERFACE Display + MODULE PROCEDURE soil_display +END INTERFACE Display + +PUBLIC :: Display + +!---------------------------------------------------------------------------- +! Soil@Soil +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION Soil_Constructor( State, SoilType, Gravel, Sand, Silt, & + & Clay, OrganicMatter, SpecificGravity, DryDensity,Gravimetric_Moisture, & + & Porosity, voidRatio, volFrac_solid, volFrac_water, volFrac_ice, & + & volFrac_air, & + & Minerals, Lambda_sat, Lambda_dry, Lambda_e, & + & ThermCondModel, ThermCondVal, UserThermCond, & + & volHeatCap_solid, volHeatCapModel, volHeatCapVal, UserVolHeatCap, & + & SFCCModel, UserSFCC_Value, UserSFCC_Slope, & + & SFCC_Theta_r, SFCC_Temp_l, SFCC_Temp_s, SFCC_Coeff ) RESULT( Ans ) + + TYPE( Soil_ ) :: Ans + INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: State + INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: SoilType + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Gravel + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Sand + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Silt + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Clay + REAL( DFP ), OPTIONAL, INTENT( IN ) :: OrganicMatter + REAL( DFP ), OPTIONAL, INTENT( IN ) :: SpecificGravity + REAL( DFP ), OPTIONAL, INTENT( IN ) :: DryDensity + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Gravimetric_Moisture + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Porosity + REAL( DFP ), OPTIONAL, INTENT( IN ) :: voidRatio + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Minerals( : ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Lambda_sat + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Lambda_dry + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Lambda_e + INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: ThermCondModel + REAL( DFP ), OPTIONAL, INTENT( IN ) :: ThermCondVal + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volHeatCap_solid + INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: volHeatCapModel + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volHeatCapVal + PROCEDURE( thermCond_get_value ), POINTER, OPTIONAL, INTENT( IN ) :: & + & UserThermCond + PROCEDURE( volHeatCap_get_value ), POINTER, OPTIONAL, INTENT( IN ) :: & + & UservolHeatCap + INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: SFCCModel + PROCEDURE( sfcc_get_value ), POINTER, OPTIONAL, INTENT( IN ) :: UserSFCC_Value + PROCEDURE( sfcc_get_value ), POINTER, OPTIONAL, INTENT( IN ) :: UserSFCC_Slope + REAL( DFP ), OPTIONAL, INTENT( IN ) :: SFCC_Theta_r + REAL( DFP ), OPTIONAL, INTENT( IN ) :: SFCC_Temp_l + REAL( DFP ), OPTIONAL, INTENT( IN ) :: SFCC_Temp_s + REAL( DFP ), OPTIONAL, INTENT( IN ) :: SFCC_Coeff +END FUNCTION Soil_Constructor +END INTERFACE + +ABSTRACT INTERFACE +PURE FUNCTION sfcc_get_value( Obj, Temp ) RESULT( Ans ) + IMPORT :: SFCCModel_, DFP + CLASS( SFCCModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ) :: Ans +END FUNCTION sfcc_get_value +END INTERFACE + +ABSTRACT INTERFACE + PURE FUNCTION thermcond_get_value( Obj, volFrac_solid, volFrac_water, & + & volFrac_ice, volFrac_air, Temp, x, y, z ) RESULT( Ans ) + + IMPORT :: ThermCondModel_, DFP + CLASS( ThermCondModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: x + REAL( DFP ), OPTIONAL, INTENT( IN ) :: y + REAL( DFP ), OPTIONAL, INTENT( IN ) :: z + REAL( DFP ) :: Ans + END FUNCTION +END INTERFACE + +ABSTRACT INTERFACE + PURE FUNCTION volHeatCap_get_value( Obj, volFrac_solid, volFrac_water, & + & volFrac_ice, volFrac_air, Temp, x, y, z ) RESULT( Ans ) + + IMPORT :: volHeatCapModel_, DFP + CLASS( volHeatCapModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: x + REAL( DFP ), OPTIONAL, INTENT( IN ) :: y + REAL( DFP ), OPTIONAL, INTENT( IN ) :: z + REAL( DFP ) :: Ans + END FUNCTION +END INTERFACE + +INTERFACE Soil + MODULE PROCEDURE Soil_Constructor +END INTERFACE Soil + +PUBLIC :: Soil + diff --git a/src/modules/oldLibrary/Material/soils_define.inc b/src/modules/oldLibrary/Material/soils_define.inc new file mode 100644 index 000000000..ccf7a0ef0 --- /dev/null +++ b/src/modules/oldLibrary/Material/soils_define.inc @@ -0,0 +1,55 @@ +!! State of soil option +INTEGER( I4B ), PARAMETER :: MAX_CHAR_LEN= 50 + +INTEGER( I4B ), PARAMETER :: STATE_FROZEN = 1 +INTEGER( I4B ), PARAMETER :: STATE_UNFROZEN = 2 +CHARACTER( LEN = MAX_CHAR_LEN ), PARAMETER :: State_Name(2) = & + & [ & + & "Frozen ", & + & "Unfrozen"] + +!! Soil Type options +INTEGER( I4B ), PARAMETER :: SOIL_FINE_GRAINED = 1 +INTEGER( I4B ), PARAMETER :: SOIL_COARSE_GRAINED = 2 +INTEGER( I4B ), PARAMETER :: SOIL_PEAT = 300 +CHARACTER( LEN = MAX_CHAR_LEN ), PARAMETER :: SoilType_Name(3) = & + & [ & + & "Fine Grained ", & + & "Coarse Grained", & + & "Peat "] + +!! Soil minerals +INTEGER( I4B ), PARAMETER :: MAX_NUM_MINERALS=20 +INTEGER( I4B ), PARAMETER :: MINERAL_QUARTZ=1 +CHARACTER( LEN = MAX_CHAR_LEN ), PARAMETER :: Mineral_Name(1) = & + & [ & + & "Quartz" ] + +!! ThermCondModel +INTEGER( I4B ), PARAMETER :: Constant_ThermCond=1 +INTEGER( I4B ), PARAMETER :: User_ThermCond=2 +INTEGER( I4B ), PARAMETER :: Johansen_ThermCond=3 + +CHARACTER( LEN = MAX_CHAR_LEN ), PARAMETER :: ThermCondModel_Name(3) = & + & [ & + & "Constant ", & + & "User Defined", & + & "Johansen " ] + +!! volumetric heat capacity +INTEGER( I4B ), PARAMETER :: constant_volHeatCap=1 +INTEGER( I4B ), PARAMETER :: user_volHeatCap=2 +INTEGER( I4B ), PARAMETER :: mix_volHeatCap=3 + +CHARACTER( LEN = MAX_CHAR_LEN ), PARAMETER :: volHeatCapModel_Name(3) = & + & [ & + & "Constant ", & + & "User Defined", & + & "Mixture " ] + +!! SFCC +INTEGER( I4B ), PARAMETER :: User_SFCC=1 +INTEGER( I4B ), PARAMETER :: Exp_SFCC=2 + +CHARACTER( LEN = MAX_CHAR_LEN ), PARAMETER :: SFCCModel_Name(2) = & + & [ "User Defined", "Exp " ] diff --git a/src/modules/oldLibrary/Material/water.inc b/src/modules/oldLibrary/Material/water.inc new file mode 100644 index 000000000..be7adcd4a --- /dev/null +++ b/src/modules/oldLibrary/Material/water.inc @@ -0,0 +1,59 @@ +!! These properties are taken from following references +!! https://www.engineeringtoolbox.com/water-liquid-gas-thermal-conductivity-temperature-pressure-d_2012.html +!! http://thermopedia.com/content/1254/ + + +TYPE( Material_ ), PARAMETER, PUBLIC :: Water = Material_( & + & thermCond = 0.59803_DFP, & +!! W/m/K at 20 degree C +!! https://www.engineeringtoolbox.com/water-liquid-gas-thermal-conductivity-temperature-pressure-d_2012.html + & specificHeatCap = 4184.4_DFP, & + & volHeatCap = 4184.4_DFP * 998.207_DFP, & +!! J/m3/K at 20 degree C +!! https://www.engineeringtoolbox.com/specific-heat-capacity-water-d_660.html + & thermDiffusivity = 0.143D-6,& +!! m2/sec at 20 degree C +!! https://www.engineeringtoolbox.com/water-steam-thermal-diffusivity-d_2058.html + & density = 999.975_DFP, & +!! kg/m3 at 4 degree C +!! https://www.engineeringtoolbox.com/water-temperature-specific-gravity-d_1179.html + & DynamicViscosity = 0.0010016_DFP, & +!! N-s/m2 at 20 degree C +!! https://www.engineeringtoolbox.com/water-dynamic-kinematic-viscosity-d_596.html + & latentHeatMelt = 334000.0_DFP, & +!! J/Kg +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & latentHeatBoil = 2256.0D+3, & +!! J/Kg +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & meltTemp = 273.15_DFP, & +!! in Kelvin +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & boilTemp = 373.15_DFP, & +!! in Kelvin +!! At 1 atm pressure +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & criticalTemp = 273.15_DFP + 373.946_DFP, & +!! Degree C +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & criticalPressure = 22.06D+6, & +!! Pa +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & triplePointPressure = 611.657_DFP, & +!! Pa +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & triplePointTemp = 273.16_DFP, & +!! in Kelvin +!! https://www.engineeringtoolbox.com/water-thermal-properties-d_162.html + & bulkModulus = 2.15D+9 & +!! N/m2 + & ) + + !---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +PUBLIC :: thermCond_water +PUBLIC :: specificHeatCap_water +PUBLIC :: density_water +PUBLIC :: volHeatCap_water \ No newline at end of file diff --git a/src/modules/oldLibrary/Material/waterfunctions.inc b/src/modules/oldLibrary/Material/waterfunctions.inc new file mode 100644 index 000000000..660495542 --- /dev/null +++ b/src/modules/oldLibrary/Material/waterfunctions.inc @@ -0,0 +1,281 @@ + +!---------------------------------------------------------------------------- +! ThermalConductivity +!---------------------------------------------------------------------------- + +PURE FUNCTION thermCond_water( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + !! internal variables + CHARACTER( LEN = 2 ) :: thermCondCase + + IF( PRESENT( Temp ) ) THEN + thermCondCase( 1:1 ) = 'T' + ELSE + thermCondCase( 1:1 ) = 't' + END IF + + IF( PRESENT( Pressure ) ) THEN + thermCondCase( 2:2 ) = 'P' + ELSE + thermCondCase( 2:2 ) = 'p' + END IF + + SELECT CASE( thermCondCase ) + CASE( 'TP' ) + Ans = thermCond_water_Temp_Pressure( Temp, Pressure ) + CASE( 'Tp' ) + Ans = thermCond_water_Temp( Temp ) + CASE( 'tP' ) + Ans = thermCond_water_Pressure( Pressure ) + CASE( 'tp' ) + Ans = Water%thermCond + END SELECT + +END FUNCTION thermCond_water + +!---------------------------------------------------------------------------- +! thermCond_water_Temp_Pressure +!---------------------------------------------------------------------------- + +PURE FUNCTION thermCond_water_Temp_Pressure(Temp, Pressure) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ), INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + Ans = 0.6065 * ( -1.48445 + 4.12292 * ( Temp / 298.15_DFP ) - 1.63866 * & + & ( Temp / 298.15_DFP ) ** 2 ) + +END FUNCTION thermCond_water_Temp_Pressure + +!---------------------------------------------------------------------------- +! thermCond_water_Temp +!---------------------------------------------------------------------------- + +PURE FUNCTION thermCond_water_Temp(Temp) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ) :: Ans + + Ans = 0.6065 * ( -1.48445 + 4.12292 * ( Temp / 298.15_DFP ) - 1.63866 * & + & ( Temp / 298.15_DFP ) ** 2 ) + +END FUNCTION thermCond_water_Temp + +!---------------------------------------------------------------------------- +! thermCond_water_Pressure +!---------------------------------------------------------------------------- + +PURE FUNCTION thermCond_water_pressure(Pressure) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + Ans = Water%thermCond +END FUNCTION thermCond_water_pressure + +!---------------------------------------------------------------------------- +! SpecificHeatCapacity +!---------------------------------------------------------------------------- + +PURE FUNCTION specificHeatCap_water( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + !! internal variables + CHARACTER( LEN = 2 ) :: specificHeatCapCase + + IF( PRESENT( Temp ) ) THEN + specificHeatCapCase( 1:1 ) = 'T' + ELSE + specificHeatCapCase( 1:1 ) = 't' + END IF + + IF( PRESENT( Pressure ) ) THEN + specificHeatCapCase( 2:2 ) = 'P' + ELSE + specificHeatCapCase( 2:2 ) = 'p' + END IF + + SELECT CASE( specificHeatCapCase ) + CASE( 'TP' ) + Ans = specificHeatCap_water_Temp_Pressure( Temp, Pressure ) + CASE( 'Tp' ) + Ans = specificHeatCap_water_Temp( Temp ) + CASE( 'tP' ) + Ans = specificHeatCap_water_Pressure( Pressure ) + CASE( 'tp' ) + Ans = Water%specificHeatCap + END SELECT + +END FUNCTION specificHeatCap_water + + +!---------------------------------------------------------------------------- +! specificHeatCap_water_Temp_Pressure +!---------------------------------------------------------------------------- + +PURE FUNCTION specificHeatCap_water_Temp_Pressure(Temp, Pressure) & + & RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ), INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + IF( Temp .LE. 373.15_DFP ) THEN + Ans = Water%SpecificHeatCap + ELSE IF( Temp .GT. 373.15_DFP ) THEN + Ans = 0.0196_DFP * Temp**2 - 13.785_DFP * Temp + 6638.6_DFP + END IF + +END FUNCTION specificHeatCap_water_Temp_Pressure + +!---------------------------------------------------------------------------- +! specificHeatCap_water_Temp +!---------------------------------------------------------------------------- + +PURE FUNCTION specificHeatCap_water_Temp(Temp) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ) :: Ans + + IF( Temp .LE. 373.15_DFP ) THEN + Ans = Water%SpecificHeatCap + ELSE IF( Temp .GT. 373.15_DFP ) THEN + Ans = 0.0196_DFP * Temp**2 - 13.785_DFP * Temp + 6638.6_DFP + END IF + +END FUNCTION specificHeatCap_water_Temp + +!---------------------------------------------------------------------------- +! specificHeatCap_water_Pressure +!---------------------------------------------------------------------------- + +PURE FUNCTION specificHeatCap_water_pressure(Pressure) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Water%specificHeatCap +END FUNCTION specificHeatCap_water_pressure + +!---------------------------------------------------------------------------- +! density_water +!---------------------------------------------------------------------------- + +PURE FUNCTION density_water( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + !! internal variables + CHARACTER( LEN = 2 ) :: densityCase + + IF( PRESENT( Temp ) ) THEN + densityCase( 1:1 ) = 'T' + ELSE + densityCase( 1:1 ) = 't' + END IF + + IF( PRESENT( Pressure ) ) THEN + densityCase( 2:2 ) = 'P' + ELSE + densityCase( 2:2 ) = 'p' + END IF + + SELECT CASE( densityCase ) + CASE( 'TP ') + Ans = density_water_Temp_Pressure( Temp, Pressure ) + CASE( 'Tp ') + Ans = density_water_Temp( Temp ) + CASE( 'tP ') + Ans = density_water_Pressure( Pressure ) + CASE( 'tp ') + Ans = Water%density + END SELECT + +END FUNCTION density_water + +!---------------------------------------------------------------------------- +! density_water_Temp_Pressure +!---------------------------------------------------------------------------- + +PURE FUNCTION density_water_Temp_Pressure( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ), INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + IF( Temp .LE. 290.0_DFP ) THEN + Ans=Water%density + ELSE + Ans=-0.0036*Temp**2 + 1.8817*Temp + 752.94 + Ans = Ans / (1.0_DFP - (Pressure - 1.0E+5) / Water%bulkModulus ) + END IF + +END FUNCTION density_water_Temp_Pressure + +!---------------------------------------------------------------------------- +! density_water_Temp +!---------------------------------------------------------------------------- + +PURE FUNCTION density_water_temp( Temp ) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ) :: Ans + + IF( Temp .LE. 290.0_DFP ) THEN + Ans=Water%density + ELSE + Ans=-0.0036*Temp**2 + 1.8817*Temp + 752.94 + END IF + +END FUNCTION density_water_temp + +!---------------------------------------------------------------------------- +! density_water_pressure +!---------------------------------------------------------------------------- + +PURE FUNCTION density_water_pressure( Pressure ) RESULT( Ans ) + REAL( DFP ), INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + Ans = Water%density / (1.0_DFP - (Pressure - 1.0E+5) / Water%bulkModulus ) +END FUNCTION density_water_pressure + +!---------------------------------------------------------------------------- +! volHeatCap_water +!---------------------------------------------------------------------------- + +PURE FUNCTION volHeatCap_water( Temp, Pressure ) RESULT( Ans ) + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Pressure + REAL( DFP ) :: Ans + + !! internal variables + CHARACTER( LEN = 2 ) :: temp_press + + IF( PRESENT( Temp ) ) THEN + temp_press( 1:1 ) = 'T' + ELSE + temp_press( 1:1 ) = 't' + END IF + + IF( PRESENT( Pressure ) ) THEN + temp_press( 2:2 ) = 'P' + ELSE + temp_press( 2:2 ) = 'p' + END IF + + SELECT CASE( temp_press ) + CASE( 'TP ') + Ans = density_water_Temp_Pressure( Temp, Pressure ) * & + & specificHeatCap_water_Temp_Pressure( Temp, Pressure ) + CASE( 'Tp ') + Ans = density_water_Temp( Temp ) * & + & specificHeatCap_water_Temp( Temp ) + CASE( 'tP ') + Ans = density_water_Pressure( Pressure ) * & + & specificHeatCap_water_pressure( Pressure ) + CASE( 'tp ') + Ans = Water%density * Water%specificHeatCap + END SELECT +END FUNCTION volHeatCap_water + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- diff --git a/src/modules/oldLibrary/MaterialProperties/PMDefine.inc b/src/modules/oldLibrary/MaterialProperties/PMDefine.inc new file mode 100644 index 000000000..60dd2f9a2 --- /dev/null +++ b/src/modules/oldLibrary/MaterialProperties/PMDefine.inc @@ -0,0 +1,5 @@ +INTEGER( I4B ), PARAMETER :: STATE_FROZEN = 1 +INTEGER( I4B ), PARAMETER :: STATE_UNFROZEN = 2 +INTEGER( I4B ), PARAMETER :: SOIL_FINE_GRAINED = 100 +INTEGER( I4B ), PARAMETER :: SOIL_COARSE_GRAINED = 200 +INTEGER( I4B ), PARAMETER :: SOIL_PEAT = 300 \ No newline at end of file diff --git a/src/modules/oldLibrary/MaterialProperties/SFCCModel_Class.f90 b/src/modules/oldLibrary/MaterialProperties/SFCCModel_Class.f90 new file mode 100644 index 000000000..00bdaf367 --- /dev/null +++ b/src/modules/oldLibrary/MaterialProperties/SFCCModel_Class.f90 @@ -0,0 +1,130 @@ +!> authors: Dr. Vikas Sharma +! +! This module consists of volumetric heat capacity model for porous media +! +MODULE SFCCModel_Class +USE GlobalData +IMPLICIT NONE +PRIVATE + +#include "./PMDefine.inc" + +!---------------------------------------------------------------------------- +! PMVolHeatCapModel_ +!---------------------------------------------------------------------------- + +TYPE, ABSTRACT :: SFCCModel_ + PROCEDURE( ExpSFCC_get_val ), POINTER, PASS( Obj ) :: getValue => NULL() + PROCEDURE( ExpSFCC_get_slope ), POINTER, PASS( Obj ) :: getSlope => NULL() + PROCEDURE( ExpSFCC_PhaseInfo ), POINTER, PASS( Obj ) :: PhaseInfo => NULL() +END TYPE SFCCModel_ + +PUBLIC :: SFCCModel_ + +!---------------------------------------------------------------------------- +! SFCCModelPointer_ +!---------------------------------------------------------------------------- +TYPE :: SFCCModelPointer_ + CLASS( SFCCModel_ ), POINTER :: Ptr=>NULL() +END TYPE SFCCModelPointer_ + +PUBLIC :: SFCCModelPointer_ + +!---------------------------------------------------------------------------- +! ExpSFCC_ +!---------------------------------------------------------------------------- + +TYPE, EXTENDS( SFCCModel_ ) :: ExpSFCC_ + REAL( DFP ) :: Theta_r = 0.0_DFP !! residual + REAL( DFP ) :: Theta_w = 0.0_DFP !! TotalWater content + REAL( DFP ) :: Temp_l = 0.0_DFP !! Freezing temp liquid side + REAL( DFP ) :: Temp_s = 0.0_DFP !! Freezing temp solid dide + REAL( DFP ) :: Coeff = 1.0_DFP !! exponent +END TYPE ExpSFCC_ + +PUBLIC :: ExpSFCC_ + +TYPE( ExpSFCC_ ), PUBLIC, PARAMETER :: TypeExpSFCC=ExpSFCC_() + +!---------------------------------------------------------------------------- +! UserSFCC_ +!---------------------------------------------------------------------------- + +TYPE, EXTENDS( SFCCModel_ ) :: UserSFCC_ +END TYPE UserSFCC_ + +PUBLIC :: UserSFCC_ + +TYPE( UserSFCC_ ), PUBLIC, PARAMETER :: TypeUserSFCC = UserSFCC_() + +!---------------------------------------------------------------------------- +! UserSFCC@User +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION UserSFCC_Pointer( ) RESULT( Ans ) + CLASS( UserSFCC_ ), POINTER :: Ans +END FUNCTION UserSFCC_Pointer +END INTERFACE + +PUBLIC :: UserSFCC_Pointer + +!---------------------------------------------------------------------------- +! Constructor@ExpSFCC +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION ExpSFCC_Pointer( Theta_r, Theta_w, Temp_l, Temp_s, & + & Coeff ) RESULT( Ans ) + CLASS( ExpSFCC_ ), POINTER :: Ans + REAL( DFP ), INTENT( IN ) :: Theta_r + REAL( DFP ), INTENT( IN ) :: Theta_w + REAL( DFP ), INTENT( IN ) :: Temp_l + REAL( DFP ), INTENT( IN ) :: Temp_s + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Coeff +END FUNCTION ExpSFCC_Pointer +END INTERFACE + +PUBLIC :: ExpSFCC_Pointer + +!---------------------------------------------------------------------------- +! getValue@expSFCC +!---------------------------------------------------------------------------- + +INTERFACE +MODULE PURE FUNCTION ExpSFCC_get_val( Obj, Temp ) RESULT( Ans ) + CLASS( SFCCModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ) :: Ans +END FUNCTION ExpSFCC_get_val +END INTERFACE + +!---------------------------------------------------------------------------- +! getSlope@expSFCC +!---------------------------------------------------------------------------- + +INTERFACE +MODULE PURE FUNCTION ExpSFCC_get_slope( Obj, Temp ) RESULT( Ans ) + CLASS( SFCCModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), INTENT( IN ) :: Temp + REAL( DFP ) :: Ans +END FUNCTION ExpSFCC_get_slope +END INTERFACE + +!---------------------------------------------------------------------------- +! PhaseInfo@expSFCC +!---------------------------------------------------------------------------- + +INTERFACE +MODULE PURE FUNCTION ExpSFCC_PhaseInfo( Obj, Temp ) RESULT( Ans ) + CLASS( SFCCModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), INTENT( IN ) :: Temp + CHARACTER( LEN = 1 ) :: Ans +END FUNCTION ExpSFCC_PhaseInfo +END INTERFACE + +!---------------------------------------------------------------------------- +! getSlope@ExpSFCC +!---------------------------------------------------------------------------- + +END MODULE SFCCModel_Class \ No newline at end of file diff --git a/src/modules/oldLibrary/MaterialProperties/ThermCondModel_Class.f90 b/src/modules/oldLibrary/MaterialProperties/ThermCondModel_Class.f90 new file mode 100644 index 000000000..c40e1c828 --- /dev/null +++ b/src/modules/oldLibrary/MaterialProperties/ThermCondModel_Class.f90 @@ -0,0 +1,159 @@ +!> authors: Dr. Vikas Sharma +! +! This module consists of several thermal conductivity model for porous +! medium +! +MODULE ThermCondModel_Class +USE GlobalData +IMPLICIT NONE +PRIVATE + +#include "./PMDefine.inc" + +!---------------------------------------------------------------------------- +! ThermCondModel_ +!---------------------------------------------------------------------------- + +TYPE, ABSTRACT :: ThermCondModel_ + REAL( DFP ) :: ConstThermCondVal = 0.0_DFP + PROCEDURE( johansen_getval ), POINTER, PASS( Obj ) :: getValue => NULL() +END TYPE ThermCondModel_ + +PUBLIC :: ThermCondModel_ + +!---------------------------------------------------------------------------- +! ThermCondModelPointer_ +!---------------------------------------------------------------------------- +TYPE :: ThermCondModelPointer_ + CLASS( ThermCondModel_ ), POINTER :: Ptr=>NULL() +END TYPE ThermCondModelPointer_ + +PUBLIC :: ThermCondModelPointer_ + +!---------------------------------------------------------------------------- +! UserThermCond_ +!---------------------------------------------------------------------------- + +TYPE, EXTENDS( ThermCondModel_ ) :: UserThermCond_ +END TYPE UserThermCond_ + +PUBLIC :: UserThermCond_ + +TYPE( UserThermCond_ ), PUBLIC, PARAMETER::TypeUserThermCond=UserThermCond_() + +!---------------------------------------------------------------------------- +! UserThermCond@User +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION UserThermCond_Pointer( ) RESULT( Ans ) + CLASS( UserThermCond_ ), POINTER :: Ans +END FUNCTION UserThermCond_Pointer +END INTERFACE + +PUBLIC :: UserThermCond_Pointer + +!---------------------------------------------------------------------------- +! getValue@User +!---------------------------------------------------------------------------- + +INTERFACE +!! This function returns the thermal conductivity values + +!> authors: Dr. Vikas Sharma +! +! This function returns the thermal conductivity values +! - `volFrac` contains volumetric fraction of solid, water, ice, air +MODULE PURE FUNCTION UserThermCond_getval( Obj, volFrac_solid, & + & volFrac_water, volFrac_ice, volFrac_air, Temp, x, y, z ) RESULT( Ans ) + CLASS( ThermCondModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: x + REAL( DFP ), OPTIONAL, INTENT( IN ) :: y + REAL( DFP ), OPTIONAL, INTENT( IN ) :: z + REAL( DFP ) :: Ans +END FUNCTION UserThermCond_getval +END INTERFACE + +!---------------------------------------------------------------------------- +! JohansenThermCond_ +!---------------------------------------------------------------------------- + +TYPE, EXTENDS( ThermCondModel_ ) :: JohansenThermCond_ + INTEGER( I4B ) :: State=STATE_UNFROZEN + INTEGER( I4B ) :: Frozen=STATE_FROZEN + INTEGER( I4B ) :: Unfrozen=STATE_UNFROZEN + INTEGER( I4B ) :: SoilType = SOIL_COARSE_GRAINED + INTEGER( I4B ) :: FineGrained = SOIL_FINE_GRAINED + INTEGER( I4B ) :: CoarseGrained = SOIL_COARSE_GRAINED + INTEGER( I4B ) :: Peat = SOIL_PEAT + + REAL( DFP ) :: Lambda_Sat = 0.0_DFP + REAL( DFP ) :: Lambda_Dry = 0.0_DFP + REAL( DFP ) :: Lambda_e = 0.0_DFP + REAL( DFP ) :: Lambda_s = 0.0_DFP + LOGICAL :: isLambda_sat_given = .FALSE. + LOGICAL :: isLambda_dry_given = .FALSE. + LOGICAL :: isLambda_e_given = .FALSE. + + REAL( DFP ) :: Gamma_d = 1600.0_DFP + REAL( DFP ) :: QuartzContent = 1.0_DFP + +END TYPE JohansenThermCond_ + +PUBLIC :: JohansenThermCond_ + +TYPE( JohansenThermCond_ ), PUBLIC, PARAMETER :: TypeJohansenThermCond & + & =JohansenThermCond_() + +!---------------------------------------------------------------------------- +! Constructor@Johansen +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION JohansenThermCond_Pointer( Lambda_Sat, Lambda_Dry, & + & Lambda_e, Gamma_d, QuartzContent, SoilState, SoilType ) & + & RESULT( Ans ) + CLASS( JohansenThermCond_ ), POINTER :: Ans + REAL( DFP ), OPTIONAL :: Lambda_Sat + REAL( DFP ), OPTIONAL :: Lambda_Dry + REAL( DFP ), OPTIONAL :: Lambda_e + REAL( DFP ), OPTIONAL :: Gamma_d + REAL( DFP ), OPTIONAL :: QuartzContent + INTEGER( I4B ), OPTIONAL :: SoilState + INTEGER( I4B ), OPTIONAL :: SoilType +END FUNCTION JohansenThermCond_Pointer +END INTERFACE + +PUBLIC :: JohansenThermCond_Pointer + +!---------------------------------------------------------------------------- +! getValue@Johansen +!---------------------------------------------------------------------------- + +INTERFACE +!! This function returns the thermal conductivity values + +!> authors: Dr. Vikas Sharma +! +! This function returns the thermal conductivity values +! - `volFrac` contains volumetric fraction of solid, water, ice, air +MODULE PURE FUNCTION johansen_getval( Obj, volFrac_solid, volFrac_water, & + & volFrac_ice, volFrac_air, Temp, x, y, z ) RESULT( Ans ) + CLASS( ThermCondModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: x + REAL( DFP ), OPTIONAL, INTENT( IN ) :: y + REAL( DFP ), OPTIONAL, INTENT( IN ) :: z + REAL( DFP ) :: Ans +END FUNCTION johansen_getval +END INTERFACE +END MODULE ThermCondModel_Class \ No newline at end of file diff --git a/src/modules/oldLibrary/MaterialProperties/VolHeatCapModel_Class.f90 b/src/modules/oldLibrary/MaterialProperties/VolHeatCapModel_Class.f90 new file mode 100644 index 000000000..6ee46a4fe --- /dev/null +++ b/src/modules/oldLibrary/MaterialProperties/VolHeatCapModel_Class.f90 @@ -0,0 +1,135 @@ +!> authors: Dr. Vikas Sharma +! +! This module consists of volumetric heat capacity model for porous media +! +MODULE VolHeatCapModel_Class +USE GlobalData +IMPLICIT NONE +PRIVATE + +#include "./PMDefine.inc" + +!---------------------------------------------------------------------------- +! VolHeatCapModel_ +!---------------------------------------------------------------------------- + +TYPE, ABSTRACT :: VolHeatCapModel_ + REAL( DFP ) :: ConstVolHeatCapVal=0.0_DFP + REAL( DFP ) :: volHeatCap_solid = 2650.0_DFP * 733.0_DFP + LOGICAL( LGT ) :: is_volHeatCap_solid_given = .FALSE. + PROCEDURE( mixvolheatcap_getval ), POINTER, PASS( Obj ) :: & + & getValue => NULL() +END TYPE VolHeatCapModel_ + +PUBLIC :: VolHeatCapModel_ + +!---------------------------------------------------------------------------- +! VolHeatCapModelPointer_ +!---------------------------------------------------------------------------- +TYPE :: VolHeatCapModelPointer_ + CLASS( VolHeatCapModel_ ), POINTER :: Ptr=>NULL() +END TYPE VolHeatCapModelPointer_ + +PUBLIC :: VolHeatCapModelPointer_ + + +!---------------------------------------------------------------------------- +! UserVolHeatCapModel_ +!---------------------------------------------------------------------------- + +TYPE, EXTENDS( volHeatCapModel_ ) :: UserVolHeatCap_ +END TYPE UserVolHeatCap_ + +TYPE( UserVolHeatCap_ ), PARAMETER, PUBLIC :: & + & TypeUserVolHeatCap = UserVolHeatCap_() + +!---------------------------------------------------------------------------- +! UserVolHeatCap_Pointer@User +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION UserVolHeatCap_Pointer( ) RESULT( Ans ) + CLASS( UserVolHeatCap_ ), POINTER :: Ans +END FUNCTION UserVolHeatCap_Pointer +END INTERFACE + +PUBLIC :: UserVolHeatCap_Pointer + +!---------------------------------------------------------------------------- +! userVolHeatCap_getval@User +!---------------------------------------------------------------------------- + +INTERFACE +!! This function returns the volumetric heat capacity values + +MODULE PURE FUNCTION userVolHeatCap_getval( Obj, volFrac_solid, & + & volFrac_water, volFrac_ice, volFrac_air, Temp, x, y, z ) RESULT( Ans ) + CLASS( VolHeatCapModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: x + REAL( DFP ), OPTIONAL, INTENT( IN ) :: y + REAL( DFP ), OPTIONAL, INTENT( IN ) :: z + REAL( DFP ) :: Ans +END FUNCTION userVolHeatCap_getval +END INTERFACE + +!---------------------------------------------------------------------------- +! MixVolHeatCap_ +!---------------------------------------------------------------------------- + +TYPE, EXTENDS( VolHeatCapModel_ ) :: MixVolHeatCap_ + INTEGER( I4B ) :: State=STATE_UNFROZEN + INTEGER( I4B ) :: Frozen=STATE_FROZEN + INTEGER( I4B ) :: Unfrozen=STATE_UNFROZEN +END TYPE MixVolHeatCap_ + +PUBLIC :: MixVolHeatCap_ + +TYPE( MixVolHeatCap_ ), PUBLIC, PARAMETER :: TypeVolHeatCap=MixVolHeatCap_() + +!---------------------------------------------------------------------------- +! Constructor@mixModel +!---------------------------------------------------------------------------- + +INTERFACE +MODULE FUNCTION MixVolHeatCap_Pointer( volHeatCap_solid, SoilState ) & + & RESULT( Ans ) + CLASS( MixVolHeatCap_ ), POINTER :: Ans + REAL( DFP ), OPTIONAL :: volHeatCap_solid + INTEGER( I4B ), OPTIONAL :: SoilState +END FUNCTION MixVolHeatCap_Pointer +END INTERFACE + +PUBLIC :: MixVolHeatCap_Pointer + +!---------------------------------------------------------------------------- +! getValue@mixModel +!---------------------------------------------------------------------------- + +INTERFACE +!! This function returns the volumetric heat capacity values + +MODULE PURE FUNCTION mixvolheatcap_getval( Obj, volFrac_solid, & + & volFrac_water, volFrac_ice, volFrac_air, Temp, x, y, z ) RESULT( Ans ) + CLASS( VolHeatCapModel_ ), INTENT( IN ) :: Obj + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_solid + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_water + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_ice + REAL( DFP ), OPTIONAL, INTENT( IN ) :: volFrac_air + REAL( DFP ), OPTIONAL, INTENT( IN ) :: Temp + REAL( DFP ), OPTIONAL, INTENT( IN ) :: x + REAL( DFP ), OPTIONAL, INTENT( IN ) :: y + REAL( DFP ), OPTIONAL, INTENT( IN ) :: z + REAL( DFP ) :: Ans +END FUNCTION mixvolheatcap_getval +END INTERFACE + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END MODULE VolHeatCapModel_Class \ No newline at end of file From 148b9cdc0f07c2a6966ec76f9c7a2a0d656faba3 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:40:02 +0900 Subject: [PATCH 084/117] Adding cmake --- src/modules/CMakeLists.txt | 267 +++++++++++++++++++++---------------- 1 file changed, 152 insertions(+), 115 deletions(-) diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 101458a00..9eae32558 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -1,324 +1,361 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# You should have received a copy of the GNU General Public License along with +# this program. If not, see # # fhash -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Fhash/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Fhash/CMakeLists.txt) # ExceptionHandler -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ExceptionHandler/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ExceptionHandler/CMakeLists.txt) # CommandLineArg -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/CommandLineArg/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/CommandLineArg/CMakeLists.txt) # AbstractFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFile/CMakeLists.txt) # FortranFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FortranFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FortranFile/CMakeLists.txt) # TxtFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/TxtFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/TxtFile/CMakeLists.txt) # CSVFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/CSVFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/CSVFile/CMakeLists.txt) # InputFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/InputFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/InputFile/CMakeLists.txt) # HDF5File -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) # XMLFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) # VTKFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) # Files -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Files/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Files/CMakeLists.txt) # HDF5File -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) # FPL -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FPL/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FPL/CMakeLists.txt) -# Toml -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) +# Toml +include(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) # Element -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Element/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Element/CMakeLists.txt) # FacetElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FacetElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FacetElement/CMakeLists.txt) # FE -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ElementFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ElementFactory/CMakeLists.txt) # IntList -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/IntList/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/IntList/CMakeLists.txt) # RealList -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/RealList/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/RealList/CMakeLists.txt) # StringList -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/StringList/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/StringList/CMakeLists.txt) # ElementList -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ElementList/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ElementList/CMakeLists.txt) # ElementPointerVector -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ElementPointerVector/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ElementPointerVector/CMakeLists.txt) # Mesh -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Mesh/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Mesh/CMakeLists.txt) # MeshPointerVector -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MeshPointerVector/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MeshPointerVector/CMakeLists.txt) # MeshConnectivity # INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MeshConnectivity/CMakeLists.txt) # Domain -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Domain/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Domain/CMakeLists.txt) # DomainConnectivity -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/DomainConnectivity/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/DomainConnectivity/CMakeLists.txt) # MeshSelection -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MeshSelection/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MeshSelection/CMakeLists.txt) # GmshAPI -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/GmshAPI/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/GmshAPI/CMakeLists.txt) # MSHFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MSHFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MSHFile/CMakeLists.txt) # AbstractFunction -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFunction/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFunction/CMakeLists.txt) # AbstractBasis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractBasis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractBasis/CMakeLists.txt) # Monomial1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Monomial1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Monomial1D/CMakeLists.txt) # Monomial2D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Monomial2D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Monomial2D/CMakeLists.txt) # Monomial3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Monomial3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Monomial3D/CMakeLists.txt) # MonomialND -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MonomialND/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MonomialND/CMakeLists.txt) # AbstractPolynomial -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractPolynomial/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractPolynomial/CMakeLists.txt) # Polynomial1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Polynomial1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Polynomial1D/CMakeLists.txt) # Polynomial2D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Polynomial2D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Polynomial2D/CMakeLists.txt) # Polynomial3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Polynomial3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Polynomial3D/CMakeLists.txt) # PolynomialND -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PolynomialND/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/PolynomialND/CMakeLists.txt) # Lagrange1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange1D/CMakeLists.txt) # Lagrange2D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange2D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange2D/CMakeLists.txt) # Lagrange3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange3D/CMakeLists.txt) # AbstractOrthopol1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractOrthopol1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractOrthopol1D/CMakeLists.txt) # Jacobi1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Jacobi1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Jacobi1D/CMakeLists.txt) # Ultraspherical1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Ultraspherical1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Ultraspherical1D/CMakeLists.txt) # Legendre1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Legendre1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Legendre1D/CMakeLists.txt) # ChebyshevFirst1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ChebyshevFirst1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ChebyshevFirst1D/CMakeLists.txt) # PolynomialFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PolynomialFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/PolynomialFactory/CMakeLists.txt) # RefElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/RefElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/RefElement/CMakeLists.txt) # AbstractFE -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFE/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFE/CMakeLists.txt) # FiniteElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FiniteElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FiniteElement/CMakeLists.txt) # MixedFiniteElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MixedFiniteElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MixedFiniteElement/CMakeLists.txt) # FiniteElementFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FiniteElementFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FiniteElementFactory/CMakeLists.txt) # Tree3R -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Tree3R/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Tree3R/CMakeLists.txt) # AbstractBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractBC/CMakeLists.txt) # DirichletBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/DirichletBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/DirichletBC/CMakeLists.txt) # NeumannBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/NeumannBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/NeumannBC/CMakeLists.txt) # NitscheBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/NitscheBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/NitscheBC/CMakeLists.txt) # BoundaryCondition -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BoundaryCondition/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BoundaryCondition/CMakeLists.txt) # UserFunction -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/UserFunction/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/UserFunction/CMakeLists.txt) # AbstractVector -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractVector/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractVector/CMakeLists.txt) # Vector -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Vector/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Vector/CMakeLists.txt) # AbstractField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractField/CMakeLists.txt) # AbstractNodeField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractNodeField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractNodeField/CMakeLists.txt) # AbstractMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMeshField/CMakeLists.txt) # ScalarMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ScalarMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ScalarMeshField/CMakeLists.txt) # STScalarMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STScalarMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STScalarMeshField/CMakeLists.txt) # VectorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VectorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VectorMeshField/CMakeLists.txt) # STVectorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STVectorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STVectorMeshField/CMakeLists.txt) # TensorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/TensorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/TensorMeshField/CMakeLists.txt) # STTensorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STTensorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STTensorMeshField/CMakeLists.txt) # AbstractElementField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractElementField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractElementField/CMakeLists.txt) # AbstractMatrixField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractMatrixField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMatrixField/CMakeLists.txt) # ScalarField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ScalarField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ScalarField/CMakeLists.txt) # ScalarFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ScalarFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ScalarFieldLis/CMakeLists.txt) # STScalarField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STScalarField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STScalarField/CMakeLists.txt) # STScalarFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STScalarFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STScalarFieldLis/CMakeLists.txt) # VectorField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VectorField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VectorField/CMakeLists.txt) # VectorFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VectorFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VectorFieldLis/CMakeLists.txt) # STVectorField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STVectorField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STVectorField/CMakeLists.txt) # STVectorFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STVectorFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STVectorFieldLis/CMakeLists.txt) # BlockNodeField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockNodeField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockNodeField/CMakeLists.txt) # BlockNodeFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockNodeFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockNodeFieldLis/CMakeLists.txt) # MatrixField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MatrixField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MatrixField/CMakeLists.txt) # MatrixFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MatrixFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MatrixFieldLis/CMakeLists.txt) # BlockMatrixField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixField/CMakeLists.txt) # BlockMatrixFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixFieldLis/CMakeLists.txt) # AbstractLinSolver -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractLinSolver/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractLinSolver/CMakeLists.txt) # Field -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Field/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Field/CMakeLists.txt) # FieldFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FieldFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FieldFactory/CMakeLists.txt) # LinSolver -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/LinSolver/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/LinSolver/CMakeLists.txt) # LinSolverLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/LinSolverLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/LinSolverLis/CMakeLists.txt) # LinSolverFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/LinSolverFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/LinSolverFactory/CMakeLists.txt) # AbstractPlot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractPlot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractPlot/CMakeLists.txt) # VTKPlot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VTKPlot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VTKPlot/CMakeLists.txt) # EasyPlplot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/EasyPlplot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/EasyPlplot/CMakeLists.txt) # PLPlot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) # Plot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Plot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Plot/CMakeLists.txt) -# easifemClasses -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/easifemClasses/CMakeLists.txt) +# AbstractMaterialModel +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMaterialModel/CMakeLists.txt) + +# AbstractSolidMechanicsModel +include(${CMAKE_CURRENT_LIST_DIR}/AbstractSolidMechanicsModel/CMakeLists.txt) + +# AbstractPoroMechanicsModel +include(${CMAKE_CURRENT_LIST_DIR}/AbstractPoroMechanicsModel/CMakeLists.txt) + +# AbstractFluidMechanicsModel +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFluidMechanicsModel/CMakeLists.txt) + +# LinearElasticModel +include(${CMAKE_CURRENT_LIST_DIR}/LinearElasticModel/CMakeLists.txt) + +# LinearPoroElasticModel +include(${CMAKE_CURRENT_LIST_DIR}/LinearPoroElasticModel/CMakeLists.txt) + +# NewtonianFluidModel +include(${CMAKE_CURRENT_LIST_DIR}/NewtonianFluidModel/CMakeLists.txt) +# MaterialFactory +include(${CMAKE_CURRENT_LIST_DIR}/MaterialFactory/CMakeLists.txt) +# AbstractMaterial +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMaterial/CMakeLists.txt) + +# SolidMaterial +include(${CMAKE_CURRENT_LIST_DIR}/SolidMaterial/CMakeLists.txt) + +# fluidMaterial +include(${CMAKE_CURRENT_LIST_DIR}/FluidMaterial/CMakeLists.txt) + +# porousMaterial +include(${CMAKE_CURRENT_LIST_DIR}/PorousMaterial/CMakeLists.txt) + +# easifemMaterials +include(${CMAKE_CURRENT_LIST_DIR}/easifemMaterials/CMakeLists.txt) + +# easifemClasses +include(${CMAKE_CURRENT_LIST_DIR}/easifemClasses/CMakeLists.txt) From abd80622f8bec6795332f403583c4f4ff6e6f348 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:40:26 +0900 Subject: [PATCH 085/117] Adding AbstractMaterial --- .../AbstractMaterial/CMakeLists.txt | 25 ++ .../includes/materialProperties.txt | 19 + ...tractMaterial_Class@ConstructorMethods.F90 | 89 +++++ .../src/AbstractMaterial_Class@GetMethods.F90 | 80 +++++ .../src/AbstractMaterial_Class@IOMethods.F90 | 338 ++++++++++++++++++ .../src/AbstractMaterial_Class@SetMethods.F90 | 125 +++++++ 6 files changed, 676 insertions(+) create mode 100644 src/submodules/AbstractMaterial/CMakeLists.txt create mode 100644 src/submodules/AbstractMaterial/includes/materialProperties.txt create mode 100644 src/submodules/AbstractMaterial/src/AbstractMaterial_Class@ConstructorMethods.F90 create mode 100644 src/submodules/AbstractMaterial/src/AbstractMaterial_Class@GetMethods.F90 create mode 100644 src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 create mode 100644 src/submodules/AbstractMaterial/src/AbstractMaterial_Class@SetMethods.F90 diff --git a/src/submodules/AbstractMaterial/CMakeLists.txt b/src/submodules/AbstractMaterial/CMakeLists.txt new file mode 100644 index 000000000..0d561b1ec --- /dev/null +++ b/src/submodules/AbstractMaterial/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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}/AbstractMaterial_Class@ConstructorMethods.F90 + ${src_path}/AbstractMaterial_Class@GetMethods.F90 + ${src_path}/AbstractMaterial_Class@SetMethods.F90 + ${src_path}/AbstractMaterial_Class@IOMethods.F90 +) diff --git a/src/submodules/AbstractMaterial/includes/materialProperties.txt b/src/submodules/AbstractMaterial/includes/materialProperties.txt new file mode 100644 index 000000000..cb259cc66 --- /dev/null +++ b/src/submodules/AbstractMaterial/includes/materialProperties.txt @@ -0,0 +1,19 @@ +massDensity +dynamicViscosity +porosity +thermalDiffusivity +diffusivity +permeability +thermalConductivity +specificHeatCapacity +volHeatCapacity +meltingTemp +boilingTemp +criticalTemp +criticalPressure +triplePointPressure +triplePointTemp +latentHeatMelting +latentHeatBoiling +volThermalCoeff +bulkModulus diff --git a/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@ConstructorMethods.F90 b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..3bbd5dc9b --- /dev/null +++ b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@ConstructorMethods.F90 @@ -0,0 +1,89 @@ +! 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(AbstractMaterial_Class) ConstructorMethods +USE BaseMethod +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "am_CheckEssentialParam()" +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & 'This routine does nothing... It should be implemented by child class.') +END PROCEDURE am_CheckEssentialParam + +!---------------------------------------------------------------------------- +! SetAbstractMaterialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetAbstractMaterialParam +CALL Set(obj=param, prefix=prefix, key="name", VALUE=name, dataType="char") +END PROCEDURE SetAbstractMaterialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_Initiate +CHARACTER(*), PARAMETER :: myName = "am_Initiate()" +CHARACTER(:), ALLOCATABLE :: prefix0 + +! main +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +CALL obj%DEALLOCATE() +! check essential param +CALL obj%CheckEssentialParam(param) + +IF (PRESENT(prefix)) THEN + prefix0 = TRIM(prefix) +ELSE + prefix0 = obj%GetPrefix() +END IF + +obj%isInit = .TRUE. + +! name +CALL GetValue(obj=param, prefix=prefix0, key="name", VALUE=obj%name) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif +END PROCEDURE am_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_Deallocate +obj%isInit = .FALSE. +obj%name = "" +obj%tProperties = 0 +! CALL Deallocate(obj%matProps) +! CALL tbl%Deallocate() +END PROCEDURE am_Deallocate + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@GetMethods.F90 b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@GetMethods.F90 new file mode 100644 index 000000000..8ab4c5b9b --- /dev/null +++ b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@GetMethods.F90 @@ -0,0 +1,80 @@ +! 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(AbstractMaterial_Class) GetMethods +USE BaseMethod +USE Fhash, ONLY: key => fhash_key +USE fhash_tbl, ONLY: FHASH_KEY_NOT_FOUND +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_GetPrefix +ans = myprefix +END PROCEDURE am_GetPrefix + +!---------------------------------------------------------------------------- +! GetMaterial +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_GetMaterialPointer +CHARACTER(*), PARAMETER :: myName = "am_GetMaterialPointer()" +LOGICAL(LGT) :: isOK +INTEGER(I4B) :: indx + +matPtr => NULL() +isOK = obj%IsMaterialPresent(name) + +IF (.NOT. isOK) THEN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: '//name//" material not found"// & + & CHAR_LF//' please use AddMaterial first.') + RETURN +END IF + +indx = 0 +CALL obj%tbl%Get(key(name), indx) + +isOK = indx .LE. obj%tProperties + +IF (.NOT. isOK) THEN + CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: out of bound index.') + RETURN +END IF + +matPtr => obj%matProps(indx)%ptr + +END PROCEDURE am_GetMaterialPointer + +!---------------------------------------------------------------------------- +! IsMaterialPresent +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_IsMaterialPresent +INTEGER(I4B) :: stat +CALL obj%tbl%check_key(key=key(name), stat=stat) +IF (stat .EQ. 0_I4B) THEN + ans = .TRUE. +ELSE + ans = .FALSE. +END IF +END PROCEDURE am_IsMaterialPresent +END SUBMODULE GetMethods diff --git a/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 new file mode 100644 index 000000000..8d4bb5bf1 --- /dev/null +++ b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 @@ -0,0 +1,338 @@ +! 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(AbstractMaterial_Class) IOMethods +USE BaseMethod +USE fhash, ONLY: fhash_tbl_t, key => fhash_key, fhash_iter_t, fhash_key_t +USE TomlUtility +USE tomlf, ONLY: & + & toml_serialize, & + & toml_get => get_value, & + & toml_len => len, & + & toml_array, & + & toml_stat +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_Display +INTEGER(I4B) :: tsize, ii +LOGICAL(LGT) :: matalloc, isOK +TYPE(fhash_iter_t) :: iter +CLASS(fhash_key_t), ALLOCATABLE :: ikey +CLASS(*), ALLOCATABLE :: idata + +CALL Display(msg, unitNo=unitNo) +CALL Display(obj%isInit, "isInitiated : ", unitNo=unitNo) +IF (.NOT. obj%isInit) RETURN +CALL Display("name : "//obj%name%chars(), unitNo=unitNo) +CALL Display(obj%tProperties, "total Properties: ", unitNo=unitNo) + +iter = fhash_iter_t(obj%tbl) + +DO WHILE (iter%next(ikey, idata)) + + SELECT TYPE (d => idata) + TYPE IS (INTEGER) + CALL Display('property ('//tostring(d)//'): '//ikey%to_string(), & + & unitNo=unitNo) + END SELECT + +END DO + +matalloc = ALLOCATED(obj%matProps) + +CALL Display(matalloc, "matProps ALLOCATED: ", unitNo=unitNo) + +IF (matalloc) THEN + tsize = SIZE(obj%matProps) + + DO ii = 1, tsize + isOK = ASSOCIATED(obj%matProps(ii)%ptr) + IF (isOK) THEN + CALL obj%matProps(ii)%ptr%Display("material Properties("// & + & tostring(ii)//"):", unitNo=unitNo) + END IF + END DO + +END IF + +END PROCEDURE am_Display + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_Export +CHARACTER(*), PARAMETER :: myName = "am_Export()" +TYPE(String) :: dsetname + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR]') + +! check +IF (.NOT. obj%isInit) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: The instance of AbstractMaterial_'// & + & CHAR_LF//'or its child-class is not '//& + & CHAR_LF//'initiated, initiate it first.') +END IF + +! check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file is not opened') +END IF + +! check +IF (.NOT. hdf5%isWrite()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file does not have write permission') +END IF + +! name +dsetname = TRIM(group)//"/name" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%name) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif +END PROCEDURE am_Export + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_Import +CHARACTER(*), PARAMETER :: myName = "am_Import()" +TYPE(String) :: dsetname + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR]') + +! check +IF (obj%isInit) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: Instance of AbstractMaterial_ or'// & + & CHAR_LF//' its child is already initiated, Deallocate it first!') +END IF + +! check +IF (.NOT. hdf5%isOpen()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file is not opened') +END IF + +! check +IF (.NOT. hdf5%isRead()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file does not have read permission') +END IF + +obj%isInit = .TRUE. + +! name +dsetname = TRIM(group)//"/name" +CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%name) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif + +END PROCEDURE am_Import + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "am_ImportFromToml1()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR]') +END PROCEDURE am_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "am_ImportFromToml2()" +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +TYPE(toml_array), POINTER :: array +INTEGER(I4B) :: origin, stat, tsize, ii +LOGICAL(LGT) :: isTable, isOK, isArray +TYPE(ParameterList_) :: param +CHARACTER(:), ALLOCATABLE :: name +CLASS(UserFunction_), POINTER :: afunc + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +! Get the entire file in table +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN +END IF + +! get tomlName from the table +node => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +! The node can be a table or array of table; first thing first. +isTable = ASSOCIATED(node) .AND. (stat .EQ. toml_stat%success) + +IF (isTable) THEN + CALL param%Initiate() + CALL SetAbstractMaterialParam(param=param, prefix=obj%GetPrefix(), & + & name=obj%GetPrefix()) + CALL obj%Initiate(param=param) + CALL param%DEALLOCATE() + + ! get name of the property from the node (table) + CALL toml_get(node, "name", name, origin=origin, stat=stat) + + isOK = ALLOCATED(name) .AND. (stat .EQ. toml_stat%success) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: cannot find/read "name" from '//tomlName// & + & ' in the config file.') + RETURN + END IF + + CALL obj%AddMaterial(name=name) + afunc => NULL() + afunc => obj%GetMaterialPointer(name=name) + isOK = ASSOCIATED(afunc) + + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error while adding a material to list.') + RETURN + END IF + + CALL afunc%ImportFromToml(table=node) + afunc => NULL() + +#ifdef DEBUG_VER + IF (PRESENT(printToml)) THEN + CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & + & unitNo=stdout) + END IF +#endif + + node => NULL() + +END IF + +!! Try for an array of material tables +IF (.NOT. isTable) THEN + array => NULL() + CALL toml_get(table, tomlName, array, origin=origin, requested=.FALSE., & + & stat=stat) + + isArray = ASSOCIATED(array) .AND. (stat .EQ. toml_stat%success) + IF (.NOT. isArray) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Cannot read/found the array '//tomlName// & + & 'from the toml config.') + RETURN + END IF + + tsize = toml_len(array) + + CALL param%Initiate() + CALL SetAbstractMaterialParam(param=param, prefix=obj%GetPrefix(), & + & name=obj%GetPrefix()) + CALL obj%Initiate(param=param) + CALL param%DEALLOCATE() + + DO ii = 1, tsize + node => NULL() + CALL toml_get(array, ii, node) + isOK = ASSOCIATED(node) + + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: In toml file '//tostring(ii)// & + & 'th material cannot be read.') + RETURN + END IF + + ! get name of the property from the node (table) + name = "" + CALL toml_get(node, "name", name, origin=origin, stat=stat) + + isOK = ALLOCATED(name) .AND. (stat .EQ. toml_stat%success) + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: cannot find/read "name" from '//tomlName// & + & 'material number '//tostring(ii)//' in the config file.') + RETURN + END IF + + CALL obj%AddMaterial(name=name) + afunc => NULL() + afunc => obj%GetMaterialPointer(name=name) + isOK = ASSOCIATED(afunc) + + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error while adding material nane='// & + & name//' to list. This is '//tostring(ii)//'th material.') + RETURN + END IF + + CALL afunc%ImportFromToml(table=node) + END DO + + afunc => NULL() + node => NULL() + array => NULL() + +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportParamFromToml()') +#endif +END PROCEDURE am_ImportFromToml2 + +END SUBMODULE IOMethods diff --git a/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@SetMethods.F90 b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@SetMethods.F90 new file mode 100644 index 000000000..f5e5e17e3 --- /dev/null +++ b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@SetMethods.F90 @@ -0,0 +1,125 @@ +! 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(AbstractMaterial_Class) SetMethods +USE BaseMethod +USE Fhash, ONLY: key => fhash_key +USE fhash_tbl, ONLY: FHASH_KEY_NOT_FOUND +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! AddMaterial +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_AddMaterial1 +CHARACTER(*), PARAMETER :: myName = "am_AddMaterial1()" +LOGICAL(LGT) :: isMatPresent, matPropsAlloc, sizeOK +INTEGER(I4B) :: matPropSize + +IF (.NOT. obj%isInit) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractMaterial_::obj is not initiated.') + RETURN +END IF + +isMatPresent = obj%IsMaterialPresent(name) +IF (isMatPresent) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: The material '//name// & + & ' is already present!') + RETURN +END IF + +obj%tProperties = obj%tProperties + 1 + +CALL obj%tbl%set(key(name), obj%tProperties) + +matPropsAlloc = ALLOCATED(obj%matProps) + +IF (matPropsAlloc) THEN + matPropSize = SIZE(obj%matProps) +ELSE + matPropSize = 0 +END IF + +sizeOK = obj%tProperties .LE. matPropSize + +IF (.NOT. sizeOK) THEN + CALL obj%ExpandMatProps() +END IF + +ALLOCATE (obj%matProps(obj%tProperties)%ptr) + +END PROCEDURE am_AddMaterial1 + +!---------------------------------------------------------------------------- +! AddMaterial +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_AddMaterial2 +INTEGER(I4B) :: ii, tsize +tsize = SIZE(name) +DO ii = 1, tsize + CALL obj%AddMaterial(name=name(ii)%chars()) +END DO +END PROCEDURE am_AddMaterial2 + +!---------------------------------------------------------------------------- +! ExpandMatProps +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_ExpandMatProps +TYPE(UserFunctionPointer_), ALLOCATABLE :: temp(:) +INTEGER(I4B) :: oldSize, newSize, ii +LOGICAL(LGT) :: matPropsAlloc + +matPropsAlloc = ALLOCATED(obj%matProps) + +IF (.NOT. matPropsAlloc) THEN + ALLOCATE (obj%matProps(thresholdSize)) + RETURN +END IF + +oldSize = SIZE(obj%matProps) + +IF (oldSize .LE. thresholdSize) THEN + newSize = INT(expandScale1 * oldSize, kind=I4B) +ELSE + newSize = INT(expandScale2 * oldSize, kind=I4B) +END IF + +ALLOCATE (temp(oldSize)) + +DO ii = 1, oldSize + temp(ii)%ptr => obj%matProps(ii)%ptr + obj%matProps(ii)%ptr => NULL() +END DO + +DEALLOCATE (obj%matProps) +ALLOCATE (obj%matProps(newSize)) + +DO ii = 1, oldSize + obj%matProps(ii)%ptr => temp(ii)%ptr + temp(ii)%ptr => NULL() +END DO + +DEALLOCATE (temp) + +END PROCEDURE am_ExpandMatProps + +END SUBMODULE SetMethods From 6f1082356f23f0f79acf206e2acdfff708ec8c57 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:40:55 +0900 Subject: [PATCH 086/117] Adding AbstractSolidMechancisModel --- .../CMakeLists.txt | 22 +++ ...tractSolidMechanicsModel_Class@Methods.F90 | 147 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt create mode 100644 src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 diff --git a/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt b/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt new file mode 100644 index 000000000..0c5653565 --- /dev/null +++ b/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/AbstractSolidMechanicsModel_Class@Methods.F90 +) diff --git a/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 new file mode 100644 index 000000000..4a2541ef1 --- /dev/null +++ b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 @@ -0,0 +1,147 @@ +! 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(AbstractSolidMechanicsModel_Class) Methods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "lem_CheckEssentialParam" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of'// & + & CHAR_LF//'AbstractSolidMechanicsModel_') +END PROCEDURE lem_CheckEssentialParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Initiate +CHARACTER(*), PARAMETER :: myName = "lem_Initiate" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & CHAR_LF//'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Initiate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Deallocate +CHARACTER(*), PARAMETER :: myName = "lem_Deallocate" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Deallocate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Import +CHARACTER(*), PARAMETER :: myName = "lem_Import" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Import + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Export +CHARACTER(*), PARAMETER :: myName = "lem_Export" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Export + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Display +CHARACTER(*), PARAMETER :: myName = "lem_Display" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Display + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetElasticParam +CHARACTER(*), PARAMETER :: myName = "lem_GetElasticParam()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_GetElasticParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetC +CHARACTER(*), PARAMETER :: myName = "lem_GetC()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +C = 0.0_DFP +END PROCEDURE lem_GetC + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetInvC +CHARACTER(*), PARAMETER :: myName = "lem_GetInvC()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +InvC = 0.0_DFP +END PROCEDURE lem_GetInvC + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetElasticityType +CHARACTER(*), PARAMETER :: myName = "lem_GetElasticityType()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +ans = 0 +END PROCEDURE lem_GetElasticityType + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetPrefix +CHARACTER(*), PARAMETER :: myName = "lem_GetPrefix()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +ans = "" +END PROCEDURE lem_GetPrefix + +END SUBMODULE Methods From 270b44bcc2c64bbac6f18540f9fcb5a3c2eb45ff Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:41:16 +0900 Subject: [PATCH 087/117] Adding FluidMaterial --- src/submodules/FluidMaterial/CMakeLists.txt | 24 ++++ ...FluidMaterial_Class@ConstructorMethods.F90 | 118 ++++++++++++++++++ .../src/FluidMaterial_Class@GetMethods.F90 | 30 +++++ .../src/FluidMaterial_Class@IOMethods.F90 | 100 +++++++++++++++ 4 files changed, 272 insertions(+) create mode 100644 src/submodules/FluidMaterial/CMakeLists.txt create mode 100644 src/submodules/FluidMaterial/src/FluidMaterial_Class@ConstructorMethods.F90 create mode 100644 src/submodules/FluidMaterial/src/FluidMaterial_Class@GetMethods.F90 create mode 100644 src/submodules/FluidMaterial/src/FluidMaterial_Class@IOMethods.F90 diff --git a/src/submodules/FluidMaterial/CMakeLists.txt b/src/submodules/FluidMaterial/CMakeLists.txt new file mode 100644 index 000000000..6f5b2e26d --- /dev/null +++ b/src/submodules/FluidMaterial/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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}/FluidMaterial_Class@ConstructorMethods.F90 + ${src_path}/FluidMaterial_Class@IOMethods.F90 + ${src_path}/FluidMaterial_Class@GetMethods.F90 +) diff --git a/src/submodules/FluidMaterial/src/FluidMaterial_Class@ConstructorMethods.F90 b/src/submodules/FluidMaterial/src/FluidMaterial_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..318a1f2e9 --- /dev/null +++ b/src/submodules/FluidMaterial/src/FluidMaterial_Class@ConstructorMethods.F90 @@ -0,0 +1,118 @@ +! 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(FluidMaterial_Class) ConstructorMethods +USE MaterialFactory +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetFluidMaterialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetFluidMaterialParam +CALL SetAbstractMaterialParam(param=param, prefix=myprefix, name=name) +CALL Set(obj=param, prefix=myprefix, key="stressStrainModel", & + & VALUE=stressStrainModel, dataType="char") +END PROCEDURE SetFluidMaterialParam + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "Fluid_CheckEssentialParam" +IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & myprefix//'/name should be present in param') +END IF +IF (ASSOCIATED(obj%StressStrainModel)) THEN + CALL obj%StressStrainModel%CheckEssentialParam(param) +END IF +END PROCEDURE Fluid_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_Initiate +CHARACTER(*), PARAMETER :: myName = "Fluid_Initiate" +TYPE(String) :: prefix0, stressStrainModel +LOGICAL(LGT) :: bool1 +! + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +IF (PRESENT(prefix)) THEN + prefix0 = prefix +ELSE + prefix0 = obj%GetPrefix() +END IF + +CALL AbstractMaterialInitiate(obj=obj, param=param, prefix=prefix0%chars()) + +! stressStrainModel + +CALL GetValue(obj=param, prefix=prefix0%chars(), key="stressStrainModel", & + & VALUE=stressStrainModel) + +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The '//prefix0//'/stressStrainModel '// & + & CHAR_LF//'is already associated, '// & + & 'nullify it first.') + RETURN +END IF + +bool1 = param%isPresent(key=prefix0//"/stressStrainModel") + +IF (bool1) THEN + obj%stressStrainModel => FluidMechanicsModelFactory( & + & stressStrainModel%chars()) + CALL obj%stressStrainModel%Initiate(param) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif +END PROCEDURE Fluid_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_Deallocate +CALL AbstractMaterialDeallocate(obj) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + DEALLOCATE (obj%stressStrainModel) + NULLIFY (obj%stressStrainModel) +END IF +END PROCEDURE Fluid_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_Final +CALL obj%DEALLOCATE() +END PROCEDURE Fluid_Final + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/FluidMaterial/src/FluidMaterial_Class@GetMethods.F90 b/src/submodules/FluidMaterial/src/FluidMaterial_Class@GetMethods.F90 new file mode 100644 index 000000000..d99b377ef --- /dev/null +++ b/src/submodules/FluidMaterial/src/FluidMaterial_Class@GetMethods.F90 @@ -0,0 +1,30 @@ +! 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(FluidMaterial_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE fluid_GetPrefix +ans = myprefix +END PROCEDURE fluid_GetPrefix + +END SUBMODULE GetMethods diff --git a/src/submodules/FluidMaterial/src/FluidMaterial_Class@IOMethods.F90 b/src/submodules/FluidMaterial/src/FluidMaterial_Class@IOMethods.F90 new file mode 100644 index 000000000..6dc54a308 --- /dev/null +++ b/src/submodules/FluidMaterial/src/FluidMaterial_Class@IOMethods.F90 @@ -0,0 +1,100 @@ +! 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(FluidMaterial_Class) IOMethods +USE MaterialFactory +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_Display +CALL Display(msg, unitNo=unitNo) +CALL AbstractMaterialDisplay(obj=obj, msg='fluidMaterial', & + & unitNo=unitNo) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL obj%stressStrainModel%Display(msg="stressStrainModel :", & + & unitNo=unitNo) +END IF +END PROCEDURE Fluid_Display + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_Import +CHARACTER(*), PARAMETER :: myName = "Fluid_Import" +TYPE(String) :: dsetname, strval + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +CALL AbstractMaterialImport(obj=obj, hdf5=hdf5, group=group) + +IF (hdf5%pathExists(TRIM(group)//"/stressStrainModel")) THEN + dsetname = TRIM(group)//"/stressStrainModel/name" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'The dataset ./stressStrainModel/name should be present') + END IF + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + obj%stressStrainModel => FluidMechanicsModelFactory( & + & TRIM(strval%chars())) + dsetname = TRIM(group)//"/stressStrainModel" + CALL obj%stressStrainModel%IMPORT(hdf5=hdf5, & + & group=dsetname%chars()) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif +END PROCEDURE Fluid_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Fluid_Export +CHARACTER(*), PARAMETER :: myName = "Fluid_Export" +TYPE(String) :: dsetname + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + +CALL AbstractMaterialExport(obj=obj, hdf5=hdf5, group=group) + +IF (ASSOCIATED(obj%stressStrainModel)) THEN + dsetname = TRIM(group)//"/stressStrainModel" + CALL obj%stressStrainModel%export(hdf5=hdf5, & + & group=dsetname%chars()) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif +END PROCEDURE Fluid_Export + +END SUBMODULE IOMethods From 9870009ae0e325667767cd2d80a82223d9dd661d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:41:24 +0900 Subject: [PATCH 088/117] Adding LinearElasticModel --- .../LinearElasticModel/CMakeLists.txt | 25 ++ ...rElasticModel_Class@ConstructorMethods.F90 | 278 ++++++++++++++ .../LinearElasticModel_Class@IOMethods.F90 | 346 ++++++++++++++++++ .../LinearElasticModel_Class@SetMethods.F90 | 37 ++ .../LinearElasticModel_Class@getMethods.F90 | 221 +++++++++++ 5 files changed, 907 insertions(+) create mode 100644 src/submodules/LinearElasticModel/CMakeLists.txt create mode 100644 src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 create mode 100644 src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 create mode 100644 src/submodules/LinearElasticModel/src/LinearElasticModel_Class@SetMethods.F90 create mode 100644 src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 diff --git a/src/submodules/LinearElasticModel/CMakeLists.txt b/src/submodules/LinearElasticModel/CMakeLists.txt new file mode 100644 index 000000000..ab819dbb1 --- /dev/null +++ b/src/submodules/LinearElasticModel/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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}/LinearElasticModel_Class@ConstructorMethods.F90 + ${src_path}/LinearElasticModel_Class@IOMethods.F90 + ${src_path}/LinearElasticModel_Class@GetMethods.F90 + ${src_path}/LinearElasticModel_Class@SetMethods.F90 +) diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..a9470c3f7 --- /dev/null +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 @@ -0,0 +1,278 @@ +! 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(LinearElasticModel_Class) ConstructorMethods +USE BaseMethod, ONLY: Input +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! setLinearElasticModelParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetLinearElasticModelParam +CHARACTER(*), PARAMETER :: myName = "SetLinearElasticModelParam" +INTEGER(I4B) :: ierr +REAL(DFP) :: lam, EE, nu, G +TYPE(String) :: astr +LOGICAL(LGT) :: isIsotropic + +CALL Set(obj=param, datatype="char", prefix=myprefix, key="name", & + & VALUE=myprefix) + +SELECT CASE (elasticityType) +CASE (IsoLinearElasticModel) + astr = "ISO" +CASE (AnisoLinearElasticModel) + astr = "ANISO" +CASE (OrthoLinearElasticModel) + astr = "ORTHO" +CASE (TransLinearElasticModel) + astr = "TRANS" +END SELECT + +CALL Set(obj=param, datatype="char", prefix=myprefix, & + & key="elasticityType", VALUE=astr%chars()) + +CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStrain", & + & VALUE=input(option=isPlaneStrain, default=.FALSE.)) + +CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStress", & + & VALUE=input(option=isPlaneStress, default=.FALSE.)) + +isIsotropic = elasticityType .EQ. IsoLinearElasticModel + +IF (isIsotropic) THEN + CALL GetElasticParam(lam=lam, G=G, EE=EE, nu=nu, & + & ShearModulus=ShearModulus, YoungsModulus=YoungsModulus, & + & PoissonRatio=PoissonRatio, lambda=lambda) + + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, key="lambda", & + & VALUE=lam) + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="shearModulus", VALUE=G) + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="poissonRatio", VALUE=nu) + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="youngsModulus", VALUE=EE) + +END IF + +IF (.NOT. isIsotropic) THEN + + IF (.NOT. PRESENT(C)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: In case of Anisotropic '// & + & CHAR_LF//' Elasticity C and invC should be present.') + END IF + + IF (.NOT. PRESENT(invC)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: In case of Anisotropic Elasticity '// & + & 'C and invC should be present') + END IF + + ierr = param%Set(key=myprefix//"/c", VALUE=C) + ierr = param%Set(key=myprefix//"/invC", VALUE=invC) +END IF + +CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="stiffnessPower", & + & VALUE=INPUT(option=stiffnessPower, default=0.0_DFP)) + +END PROCEDURE SetLinearElasticModelParam + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "lem_CheckEssentialParam" +CHARACTER(15) :: charVar +INTEGER(I4B) :: ierr, cc +INTEGER(I4B), ALLOCATABLE :: shapeOfC(:) +LOGICAL(LGT) :: isPlaneStress, isPlaneStrain + +IF (.NOT. param%IsPresent(key=myprefix//"/name")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/name should be present in param') +END IF + +IF (.NOT. param%IsPresent(key=myprefix//"/elasticityType")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/elasticityType should be present in param') +END IF + +IF (param%IsPresent(key=myprefix//"/isPlaneStress")) THEN + ierr = param%get(key=myprefix//"/isPlaneStress", & + & VALUE=isPlaneStress) +END IF + +IF (param%IsPresent(key=myprefix//"/isPlaneStrain")) THEN + ierr = param%get(key=myprefix//"/isPlaneStrain", & + & VALUE=isPlaneStrain) +END IF + +IF (isPlaneStress .AND. isPlaneStrain) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'Both '//myprefix//'/isPlaneStress and '//myprefix//'/ & + & isPlaneStrain parameters are true, which is conflicting with each & + & other. Choose one.') +END IF + +ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) +cc = 0 + +IF (TRIM(charVar) .EQ. "ISO") THEN + IF (.NOT. param%IsPresent(key=myprefix//"/lambda")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/lambda should be present in param') + + IF (.NOT. param%IsPresent(key=myprefix//"/shearModulus")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/shearModulus should be present in param') + + IF (.NOT. param%IsPresent(key=myprefix//"/poissonRatio")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/poissonRatio should be present in param') + + IF (.NOT. param%IsPresent(key=myprefix//"/youngsModulus")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/youngsModulus should be present in param') + +ELSE + + IF (.NOT. param%IsPresent(key=myprefix//"/c")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/c should be present for anisotropic elasticity') + RETURN + END IF + + ierr = param%GetShape(key=myprefix//"/c", shape=shapeOfC) + IF (ANY(shapeOfC .NE. [6, 6])) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The shape of '//myprefix//'/c should be [6,6]') + RETURN + END IF + + IF (.NOT. param%IsPresent(key=myprefix//"/invC")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/invC should be present for anisotropic elasticity') + RETURN + END IF + + ierr = param%GetShape(key=myprefix//"/invC", shape=shapeOfC) + IF (ANY(shapeOfC .NE. [6, 6])) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The shape of '//myprefix//'/invC should be [6,6]') + RETURN + END IF + +END IF + +END PROCEDURE lem_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Initiate +CHARACTER(*), PARAMETER :: myName = "lem_Initiate" +CHARACTER(15) :: charVar +INTEGER(I4B) :: ierr +LOGICAL(LGT) :: isPlaneStress +LOGICAL(LGT) :: isPlaneStrain + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +CALL obj%CheckEssentialParam(param) +CALL obj%SetIsInitiated(.TRUE.) +CALL obj%SetName(myprefix) +ierr = param%get(key=myprefix//"/isPlaneStress", VALUE=isPlaneStress) +CALL obj%SetPlaneStress(isPlaneStress) +ierr = param%get(key=myprefix//"/isPlaneStrain", VALUE=isPlaneStrain) +CALL obj%SetPlaneStrain(isPlaneStrain) +ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) + +IF (TRIM(charVar) .EQ. "ISO") THEN + obj%elasticityType = IsoLinearElasticModel +ELSE IF (TRIM(charVar) .EQ. "ANISO") THEN + obj%elasticityType = AnisoLinearElasticModel +ELSE IF (TRIM(charVar) .EQ. "ORTHO") THEN + obj%elasticityType = OrthoLinearElasticModel +ELSE IF (TRIM(charVar) .EQ. "TRANS") THEN + obj%elasticityType = TransLinearElasticModel +END IF + +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + ierr = param%get(key=myprefix//"/lambda", VALUE=obj%lambda) + ierr = param%get(key=myprefix//"/shearModulus", VALUE=obj%G) + ierr = param%get(key=myprefix//"/youngsModulus", VALUE=obj%E) + ierr = param%get(key=myprefix//"/poissonRatio", VALUE=obj%nu) + IF (isPlaneStress) THEN + CALL get_PlaneStress_C_InvC(C=obj%C, invC=obj%invC, & + & youngsModulus=obj%E, nu=obj%nu) + ELSEIF (isPlaneStrain) THEN + CALL get_PlaneStrain_C_InvC(C=obj%C, invC=obj%invC, & + & youngsModulus=obj%E, nu=obj%nu) + ELSE + CALL get_3D_C_InvC(C=obj%C, invC=obj%invC, & + & youngsModulus=obj%E, nu=obj%nu) + END IF +ELSE + ierr = param%get(key=myprefix//"/c", VALUE=obj%C) + ierr = param%get(key=myprefix//"/invC", VALUE=obj%invC) +END IF + +ierr = param%get(key=myprefix//"/stiffnessPower", VALUE=obj%stiffnessPower) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif + +END PROCEDURE lem_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Deallocate +CALL AbstractSolidMechanicsModelDeallocate(obj) +obj%elasticityType = -1 +obj%nu = 0.0 +obj%G = 0.0 +obj%E = 0.0 +obj%lambda = 0.0 +obj%C = 0.0_DFP +obj%invC = 0.0_DFP +obj%stiffnessPower = 0.0_DFP +END PROCEDURE lem_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Final +CALL obj%DEALLOCATE() +END PROCEDURE lem_Final + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 new file mode 100644 index 000000000..d797e95cf --- /dev/null +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 @@ -0,0 +1,346 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This submodule contains input-output methods + +SUBMODULE(LinearElasticModel_Class) IOMethods +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Import +CHARACTER(*), PARAMETER :: myName = "lem_Import" +INTEGER(I4B) :: elasticityType +TYPE(String) :: dsetname, strval +LOGICAL(LGT) :: isPlaneStrain, isPlaneStress +REAL(DFP) :: poissonRatio, youngsModulus, shearModulus, lambda, stiffnessPower +REAL(DFP), ALLOCATABLE :: C(:, :), invC(:, :) +TYPE(ParameterList_) :: param + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +IF (obj%isInitiated()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: The object is already initiated, deallocate first!') +END IF + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file is not opened') +END IF + +IF (.NOT. hdf5%isRead()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: HDF5 file does not have read permission') +END IF + +! READ name + +dsetname = TRIM(group)//"/name" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset name should be present') +END IF +CALL hdf5%READ(dsetname=dsetname%chars(), vals=obj%name) + +! READ elasticityType +dsetname = TRIM(group)//"/elasticityType" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset elasticityType should be present') +END IF +CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + +SELECT CASE (TRIM(strval%chars())) +CASE ("ISO") + elasticityType = IsoLinearElasticModel +CASE ("ANISO") + elasticityType = AnisoLinearElasticModel +CASE ("ORTHO") + elasticityType = OrthoLinearElasticModel +CASE ("TRANS") + elasticityType = TransLinearElasticModel +END SELECT + +! READ isPlaneStrain +dsetname = TRIM(group)//"/isPlaneStrain" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=isPlaneStrain) +ELSE + isPlaneStrain = .FALSE. +END IF + +! READ isPlaneStress +dsetname = TRIM(group)//"/isPlaneStress" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=isPlaneStress) +ELSE + isPlaneStress = .FALSE. +END IF + +IF (elasticityType .EQ. IsoLinearElasticModel) THEN + dsetname = TRIM(group)//"/poissonRatio" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset poissonRatio should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=poissonRatio) + END IF + dsetname = TRIM(group)//"/youngsModulus" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset youngsModulus should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=youngsModulus) + END IF + dsetname = TRIM(group)//"/shearModulus" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset shearModulus should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=shearModulus) + END IF + dsetname = TRIM(group)//"/lambda" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset lambda should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=lambda) + END IF +ELSE + dsetname = TRIM(group)//"/c" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset c should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=C) + END IF + dsetname = TRIM(group)//"/invC" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset invC should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=invC) + END IF +END IF + +dsetname = TRIM(group)//"/stiffnessPower" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=stiffnessPower) +ELSE + stiffnessPower = 0.0_DFP +END IF + +CALL param%initiate() + +CALL setLinearElasticModelParam( & + & param=param, & + & elasticityType=elasticityType, & + & isPlaneStrain=isPlaneStrain, & + & isPlaneStress=isPlaneStress, & + & poissonRatio=poissonRatio, & + & youngsModulus=youngsModulus, & + & shearModulus=shearModulus, & + & lambda=lambda, & + & stiffnessPower=stiffnessPower, & + & C=C, & + & invC=invC) + +CALL obj%initiate(param) + +CALL param%DEALLOCATE() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif +END PROCEDURE lem_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Export +CHARACTER(*), PARAMETER :: myName = "lem_Export" +TYPE(String) :: dsetname, strval + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + +IF (.NOT. obj%isInitiated()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The object is not initiated, initiate first!') +END IF + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file is not opened') +END IF + +IF (.NOT. hdf5%isWrite()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file does not have write permission') +END IF + +! WRITE name +dsetname = TRIM(group)//"/name" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%name) + +! WRITE elasticityType +dsetname = TRIM(group)//"/elasticityType" +SELECT CASE (obj%elasticityType) +CASE (IsoLinearElasticModel) + strval = "ISO" +CASE (AnisoLinearElasticModel) + strval = "ANISO" +CASE (OrthoLinearElasticModel) + strval = "ORTHO" +CASE (TransLinearElasticModel) + strval = "TRANS" +END SELECT +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) + +! WRITE isPlaneStrain +dsetname = TRIM(group)//"/isPlaneStrain" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isPlaneStrain()) + +! WRITE isPlaneStress +dsetname = TRIM(group)//"/isPlaneStress" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isPlaneStress()) + +! C and invC +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + dsetname = TRIM(group)//"/poissonRatio" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%nu) + dsetname = TRIM(group)//"/youngsModulus" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%E) + dsetname = TRIM(group)//"/shearModulus" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%G) + dsetname = TRIM(group)//"/lambda" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%lambda) + dsetname = TRIM(group)//"/c" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%C) + dsetname = TRIM(group)//"/invC" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%invC) +ELSE + dsetname = TRIM(group)//"/c" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%C) + dsetname = TRIM(group)//"/invC" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%invC) +END IF + +dsetname = TRIM(group)//"/stiffnessPower" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%stiffnessPower) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif + +END PROCEDURE lem_Export + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Display +LOGICAL(LGT) :: isPlaneStress +LOGICAL(LGT) :: isPlaneStrain + +CALL Display(TRIM(msg), unitNo=unitNo) + +IF (.NOT. obj%isInitiated()) THEN + CALL Display("LinearElasticModel is not initiated! & + & Noting to display", unitNo=unitNo) +END IF + +isPlaneStress = obj%isPlaneStress() +isPlaneStrain = obj%isPlaneStrain() + +CALL Display("name: LinearElasticModel", unitNo=unitNo) + +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + CALL Display("elasticityType: IsoLinearElasticModel", & + & unitNo=unitNo) +ELSE IF (obj%elasticityType .EQ. AnisoLinearElasticModel) THEN + CALL Display("elasticityType: AnisoLinearElasticModel", & + & unitNo=unitNo) +ELSE IF (obj%elasticityType .EQ. OrthoLinearElasticModel) THEN + CALL Display("elasticityType: OrthoLinearElasticModel", & + & unitNo=unitNo) +ELSE IF (obj%elasticityType .EQ. TransLinearElasticModel) THEN + CALL Display("elasticityType: TransLinearElasticModel", & + & unitNo=unitNo) +END IF + +IF (isPlaneStress) THEN + CALL Display("isPlaneStress: True", unitNo=unitNo) +ELSE + CALL Display("isPlaneStress: False", unitNo=unitNo) +END IF + +IF (isPlaneStrain) THEN + CALL Display("isPlaneStrain: True", unitNo=unitNo) +ELSE + CALL Display("isPlaneStrain: False", unitNo=unitNo) +END IF + +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + CALL Display(obj%nu, "poisson ratio: ", unitNo=unitNo) + CALL Display(obj%G, "shear modulus: ", unitNo=unitNo) + CALL Display(obj%E, "youngs modulus: ", unitNo=unitNo) + CALL Display(obj%lambda, "lambda: ", unitNo=unitNo) + + IF (isPlaneStress .OR. isPlaneStrain) THEN + CALL Display(obj%C(1:3, 1:3), "tangent matrix: ", & + & unitNo=unitNo) + CALL Display(obj%invC(1:3, 1:3), "compliance matrix: ", & + & unitNo=unitNo) + ELSE + CALL Display(obj%C, "tangent matrix: ", & + & unitNo=unitNo) + CALL Display(obj%invC, "compliance matrix: ", & + & unitNo=unitNo) + END IF + +ELSE + + CALL Display(obj%C, "tangent matrix: ", unitNo=unitNo) + CALL Display(obj%invC, "compliance matrix: ", unitNo=unitNo) + +END IF + +CALL Display(obj%stiffnessPower, "stiffnessPower: ", unitNo=unitNo) + +END PROCEDURE lem_Display + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE IOMethods diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@SetMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@SetMethods.F90 new file mode 100644 index 000000000..90162e70e --- /dev/null +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@SetMethods.F90 @@ -0,0 +1,37 @@ +! 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(LinearElasticModel_Class) SetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_SetParam +IF (PRESENT(elasticityType)) obj%elasticityType = elasticityType +IF (PRESENT(nu)) obj%nu = nu +IF (PRESENT(G)) obj%G = G +IF (PRESENT(youngsModulus)) obj%E = youngsModulus +IF (PRESENT(lambda)) obj%lambda = lambda +IF (PRESENT(C)) obj%C = C +IF (PRESENT(invC)) obj%invC = invC +IF (PRESENT(stiffnessPower)) obj%stiffnessPower = stiffnessPower +END PROCEDURE lem_SetParam + +END SUBMODULE SetMethods diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 new file mode 100644 index 000000000..aaa15238d --- /dev/null +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 @@ -0,0 +1,221 @@ +! 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(LinearElasticModel_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! GetElasticParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE GetElasticParam +LOGICAL(LGT) :: isLam, isG, isNu, isE +REAL(DFP) :: r + +IF (PRESENT(shearModulus)) THEN + isG = .TRUE. + G = shearModulus +ELSE + isG = .FALSE. +END IF +IF (PRESENT(youngsModulus)) THEN + isE = .TRUE. + EE = youngsModulus +ELSE + isE = .FALSE. +END IF +IF (PRESENT(poissonRatio)) THEN + isNu = .TRUE. + Nu = poissonRatio +ELSE + isNu = .FALSE. +END IF +IF (PRESENT(lambda)) THEN + isLam = .TRUE. + lam = lambda +ELSE + isLam = .FALSE. +END IF +!1 +IF (isNu .AND. isE) THEN + lam = EE * nu / (1.0 + nu) / (1.0 - 2.0 * nu) + G = EE * 0.5_DFP / (1.0 + nu) + !2 +ELSE IF (isG .AND. isE) THEN + lam = G * (EE - 2.0 * G) / (3.0 * G - EE) + nu = (EE - 2.0 * G) * 0.5_DFP / G + !3 +ELSE IF (isNu .AND. isG) THEN + lam = 2.0 * G * nu / (1.0 - 2.0 * nu) + EE = 2.0 * G * (1.0 + nu) + !4 +ELSE IF (isLam .AND. isG) THEN + EE = G * (3.0 * lam + 2.0 * G) / (lam + G) + nu = lam * 0.5 / (lam + G) + !5 +ELSE IF (isE .AND. isLam) THEN + r = SQRT(EE * EE + 9.0 * lam * lam + 2.0 * EE * lam) + G = (EE - 3.0 * lam + r) / 4.0 + nu = 2.0 * lam / (EE + lam + r) + !6 +ELSE IF (isNu .AND. isLam) THEN + EE = lam * (1.0 + nu) * (1.0 - 2.0 * nu) / nu + G = lam * (1.0 - 2.0 * nu) * 0.5_DFP / nu +END IF +END PROCEDURE GetElasticParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Get_PlaneStress_C_invC +REAL(DFP) :: a +C = 0.0_DFP +invC = 0.0_DFP +a = youngsModulus / (1.0 - nu * nu) +C(1, 1) = a +C(2, 2) = C(1, 1) +C(3, 3) = a * (1.0 - nu) * 0.5_DFP +C(1, 2) = a * nu +C(2, 1) = C(1, 2) +a = 1.0_DFP / youngsModulus +invC(1, 1) = a +invC(2, 2) = invC(1, 1) +invC(3, 3) = a * 2.0_DFP * (1.0 + nu) +invC(1, 2) = -nu * a +invC(2, 1) = invC(1, 2) +END PROCEDURE Get_PlaneStress_C_invC + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Get_PlaneStrain_C_invC +REAL(DFP) :: a +C = 0.0_DFP +invC = 0.0_DFP +a = youngsModulus / (1.0 - 2.0 * nu) / (1.0 + nu) +C(1, 1) = a * (1.0 - nu) +C(2, 2) = C(1, 1) +C(3, 3) = a * (1.0 - 2.0 * nu) * 0.5_DFP +C(1, 2) = a * nu +C(2, 1) = C(1, 2) +a = (1.0 + nu) / youngsModulus +invC(1, 1) = a * (1.0 - nu) +invC(2, 2) = invC(1, 1) +invC(3, 3) = 2.0_DFP * a +invC(1, 2) = -nu * a +invC(2, 1) = invC(1, 2) +END PROCEDURE Get_PlaneStrain_C_invC + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Get_3D_C_invC +REAL(DFP) :: a +C = 0.0_DFP +invC = 0.0_DFP +a = youngsModulus / (1.0 + nu) / (1.0 - 2.0 * nu) +C(1, 1) = (1.0 - nu) * a +C(2, 2) = C(1, 1) +C(3, 3) = C(1, 1) +C(4, 4) = a * 0.5 * (1.0 - 2.0 * nu) +C(5, 5) = C(4, 4) +C(6, 6) = C(4, 4) +C(1, 2) = nu * a +C(1, 3) = C(1, 2) +C(2, 1) = C(1, 2) +C(2, 3) = C(1, 2) +C(3, 1) = C(1, 2) +C(3, 2) = C(1, 2) +a = 1.0_DFP / youngsModulus +invC(1, 1) = a +invC(2, 2) = invC(1, 1) +invC(3, 3) = invC(1, 1) +invC(4, 4) = a * 2.0 * (1.0 + nu) +invC(5, 5) = invC(4, 4) +invC(6, 6) = invC(4, 4) +invC(1, 2) = -nu * a +invC(1, 3) = invC(1, 2) +invC(2, 1) = invC(1, 2) +invC(2, 3) = invC(1, 2) +invC(3, 1) = invC(1, 2) +invC(3, 2) = invC(1, 2) +END PROCEDURE Get_3D_C_invC + +!---------------------------------------------------------------------------- +! GetElasticParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetElasticParam +IF (PRESENT(poissonRatio)) poissonRatio = obj%nu +IF (PRESENT(shearModulus)) shearModulus = obj%G +IF (PRESENT(youngsModulus)) youngsModulus = obj%E +IF (PRESENT(lambda)) lambda = obj%lambda +IF (PRESENT(stiffnessPower)) stiffnessPower = obj%stiffnessPower +END PROCEDURE lem_GetElasticParam + +!---------------------------------------------------------------------------- +! GetC +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetC +C = obj%C +END PROCEDURE lem_GetC + +!---------------------------------------------------------------------------- +! GetinvC +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetinvC +invC = obj%invC +END PROCEDURE lem_GetinvC + +!---------------------------------------------------------------------------- +! GetElasticityType +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetElasticityType +ans = obj%elasticityType +END PROCEDURE lem_GetElasticityType + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetPrefix +ans = myPrefix +END PROCEDURE lem_GetPrefix + +!---------------------------------------------------------------------------- +! GetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_GetParam +IF (PRESENT(elasticityType)) elasticityType = obj%elasticityType +IF (PRESENT(nu)) nu = obj%nu +IF (PRESENT(G)) G = obj%G +IF (PRESENT(youngsModulus)) youngsModulus = obj%E +IF (PRESENT(lambda)) lambda = obj%lambda +IF (PRESENT(C)) C = obj%C +IF (PRESENT(invC)) invC = obj%invC +IF (PRESENT(stiffnessPower)) stiffnessPower = obj%stiffnessPower +END PROCEDURE lem_GetParam + +END SUBMODULE GetMethods From 25b52be34b65009ec663c9e78aadb4c67d2a4d47 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:42:46 +0900 Subject: [PATCH 089/117] Adding LinearPoroElasticModel --- .../LinearPoroElasticModel/CMakeLists.txt | 25 ++ ...oElasticModel_Class@ConstructorMethods.F90 | 271 +++++++++++++++ ...LinearPoroElasticModel_Class@IOMethods.F90 | 320 ++++++++++++++++++ ...inearPoroElasticModel_Class@SetMethods.F90 | 36 ++ ...inearPoroElasticModel_Class@getMethods.F90 | 71 ++++ 5 files changed, 723 insertions(+) create mode 100644 src/submodules/LinearPoroElasticModel/CMakeLists.txt create mode 100644 src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 create mode 100644 src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 create mode 100644 src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@SetMethods.F90 create mode 100644 src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@getMethods.F90 diff --git a/src/submodules/LinearPoroElasticModel/CMakeLists.txt b/src/submodules/LinearPoroElasticModel/CMakeLists.txt new file mode 100644 index 000000000..8ed562436 --- /dev/null +++ b/src/submodules/LinearPoroElasticModel/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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}/LinearPoroElasticModel_Class@ConstructorMethods.F90 + ${src_path}/LinearPoroElasticModel_Class@IOMethods.F90 + ${src_path}/LinearPoroElasticModel_Class@GetMethods.F90 + ${src_path}/LinearPoroElasticModel_Class@SetMethods.F90 +) diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..9b817848d --- /dev/null +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 @@ -0,0 +1,271 @@ +! 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(LinearPoroElasticModel_Class) ConstructorMethods +USE BaseMethod, ONLY: Input +USE easifemMaterials +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! setLinearPoroElasticModelParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetLinearPoroElasticModelParam +CHARACTER(*), PARAMETER :: myName = "SetLinearPoroElasticModelParam" +INTEGER(I4B) :: ierr +REAL(DFP) :: lam, EE, nu, G +TYPE(String) :: astr +LOGICAL(LGT) :: isIsotropic + +CALL Set(obj=param, datatype="char", prefix=myprefix, key="name", & + & VALUE=myprefix) + +SELECT CASE (elasticityType) +CASE (IsoLinearElasticModel) + astr = "ISO" +CASE (AnisoLinearElasticModel) + astr = "ANISO" +CASE (OrthoLinearElasticModel) + astr = "ORTHO" +CASE (TransLinearElasticModel) + astr = "TRANS" +END SELECT + +CALL Set(obj=param, datatype="char", prefix=myprefix, & + & key="elasticityType", VALUE=astr%chars()) + +CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStrain", & + & VALUE=input(option=isPlaneStrain, default=.FALSE.)) + +CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStress", & + & VALUE=input(option=isPlaneStress, default=.FALSE.)) + +isIsotropic = elasticityType .EQ. IsoLinearElasticModel + +IF (isIsotropic) THEN + CALL GetElasticParam(lam=lam, G=G, EE=EE, nu=nu, & + & ShearModulus=ShearModulus, YoungsModulus=YoungsModulus, & + & PoissonRatio=PoissonRatio, lambda=lambda) + + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, key="lambda", & + & VALUE=lam) + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="shearModulus", VALUE=G) + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="poissonRatio", VALUE=nu) + CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & + & key="youngsModulus", VALUE=EE) + +END IF + +IF (.NOT. isIsotropic) THEN + + IF (.NOT. PRESENT(C)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: In case of Anisotropic '// & + & CHAR_LF//' Elasticity C and invC should be present.') + END IF + + IF (.NOT. PRESENT(invC)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: In case of Anisotropic Elasticity '// & + & 'C and invC should be present') + END IF + + ierr = param%Set(key=myprefix//"/c", VALUE=C) + ierr = param%Set(key=myprefix//"/invC", VALUE=invC) +END IF + +END PROCEDURE SetLinearPoroElasticModelParam + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "lpem_CheckEssentialParam" +CHARACTER(15) :: charVar +INTEGER(I4B) :: ierr, cc +INTEGER(I4B), ALLOCATABLE :: shapeOfC(:) +LOGICAL(LGT) :: isPlaneStress, isPlaneStrain + +IF (.NOT. param%IsPresent(key=myprefix//"/name")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/name should be present in param') +END IF + +IF (.NOT. param%IsPresent(key=myprefix//"/elasticityType")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/elasticityType should be present in param') +END IF + +IF (param%IsPresent(key=myprefix//"/isPlaneStress")) THEN + ierr = param%get(key=myprefix//"/isPlaneStress", & + & VALUE=isPlaneStress) +END IF + +IF (param%IsPresent(key=myprefix//"/isPlaneStrain")) THEN + ierr = param%get(key=myprefix//"/isPlaneStrain", & + & VALUE=isPlaneStrain) +END IF + +IF (isPlaneStress .AND. isPlaneStrain) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'Both '//myprefix//'/isPlaneStress and '//myprefix//'/ & + & isPlaneStrain parameters are true, which is conflicting with each & + & other. Choose one.') +END IF + +ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) +cc = 0 + +IF (TRIM(charVar) .EQ. "ISO") THEN + IF (.NOT. param%IsPresent(key=myprefix//"/lambda")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/lambda should be present in param') + + IF (.NOT. param%IsPresent(key=myprefix//"/shearModulus")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/shearModulus should be present in param') + + IF (.NOT. param%IsPresent(key=myprefix//"/poissonRatio")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/poissonRatio should be present in param') + + IF (.NOT. param%IsPresent(key=myprefix//"/youngsModulus")) & + & CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/youngsModulus should be present in param') + +ELSE + + IF (.NOT. param%IsPresent(key=myprefix//"/c")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/c should be present for anisotropic elasticity') + RETURN + END IF + + ierr = param%GetShape(key=myprefix//"/c", shape=shapeOfC) + IF (ANY(shapeOfC .NE. [6, 6])) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The shape of '//myprefix//'/c should be [6,6]') + RETURN + END IF + + IF (.NOT. param%IsPresent(key=myprefix//"/invC")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/invC should be present for anisotropic elasticity') + RETURN + END IF + + ierr = param%GetShape(key=myprefix//"/invC", shape=shapeOfC) + IF (ANY(shapeOfC .NE. [6, 6])) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The shape of '//myprefix//'/invC should be [6,6]') + RETURN + END IF + +END IF +END PROCEDURE lpem_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_Initiate +CHARACTER(*), PARAMETER :: myName = "lpem_Initiate" +CHARACTER(15) :: charVar +INTEGER(I4B) :: ierr +LOGICAL(LGT) :: isPlaneStrain +LOGICAL(LGT) :: isPlaneStress + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +CALL obj%CheckEssentialParam(param) +CALL obj%SetIsInitiated(.TRUE.) +CALL obj%SetName(myprefix) +ierr = param%get(key=myprefix//"/isPlaneStress", VALUE=isPlaneStress) +ierr = param%get(key=myprefix//"/isPlaneStrain", VALUE=isPlaneStrain) +CALL obj%SetPlaneStress(isPlaneStress) +CALL obj%SetPlaneStrain(isPlaneStrain) +ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) + +IF (TRIM(charVar) .EQ. "ISO") THEN + obj%elasticityType = IsoLinearElasticModel +ELSE IF (TRIM(charVar) .EQ. "ANISO") THEN + obj%elasticityType = AnIsoLinearElasticModel +ELSE IF (TRIM(charVar) .EQ. "ORTHO") THEN + obj%elasticityType = OrthoLinearElasticModel +ELSE IF (TRIM(charVar) .EQ. "TRANS") THEN + obj%elasticityType = TransLinearElasticModel +END IF + +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + ierr = param%get(key=myprefix//"/lambda", VALUE=obj%lambda) + ierr = param%get(key=myprefix//"/shearModulus", VALUE=obj%G) + ierr = param%get(key=myprefix//"/youngsModulus", VALUE=obj%E) + ierr = param%get(key=myprefix//"/poissonRatio", VALUE=obj%nu) + IF (isPlaneStress) THEN + CALL get_PlaneStress_C_InvC(C=obj%C, invC=obj%invC, & + & youngsModulus=obj%E, nu=obj%nu) + ELSEIF (isPlaneStrain) THEN + CALL get_PlaneStrain_C_InvC(C=obj%C, invC=obj%invC, & + & youngsModulus=obj%E, nu=obj%nu) + ELSE + CALL get_3D_C_InvC(C=obj%C, invC=obj%invC, youngsModulus=obj%E, & + & nu=obj%nu) + END IF +ELSE + ierr = param%get(key=myprefix//"/c", VALUE=obj%C) + ierr = param%get(key=myprefix//"/invC", VALUE=obj%invC) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif + +END PROCEDURE lpem_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_Deallocate +CALL AbstractSolidMechanicsModelDeallocate(obj) +obj%elasticityType = -1 +obj%nu = 0.0 +obj%G = 0.0 +obj%E = 0.0 +obj%lambda = 0.0 +obj%C = 0.0_DFP +obj%invC = 0.0_DFP +END PROCEDURE lpem_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_Final +CALL obj%DEALLOCATE() +END PROCEDURE lpem_Final + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 new file mode 100644 index 000000000..83f4f729a --- /dev/null +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 @@ -0,0 +1,320 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This submodule contains input-output methods + +SUBMODULE(LinearPoroElasticModel_Class) IOMethods +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_Import +CHARACTER(*), PARAMETER :: myName = "lpem_Import" +INTEGER(I4B) :: elasticityType +TYPE(String) :: dsetname, strval +LOGICAL(LGT) :: isPlaneStrain, isPlaneStress +REAL(DFP) :: PoissonRatio, YoungsModulus, ShearModulus, lambda +REAL(DFP), ALLOCATABLE :: C(:, :), invC(:, :) +TYPE(ParameterList_) :: param + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//"::"//myName//" - "// & + & "[START] Import()") +#endif + +IF (obj%isInitiated()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The object is already initiated, deallocate first!') +END IF + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file is not opened') +END IF + +IF (.NOT. hdf5%isRead()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file does not have read permission') +END IF + +dsetname = TRIM(group)//"/name" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset name should be present') +END IF + +CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) +CALL obj%SetName(strval%chars()) +strval = "" + +!> READ elasticityType +dsetname = TRIM(group)//"/elasticityType" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The dataset elasticityType should be present') +END IF + +CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) +SELECT CASE (TRIM(strval%chars())) +CASE ("ISO") + elasticityType = IsoLinearElasticModel +CASE ("ANISO") + elasticityType = AnisoLinearElasticModel +CASE ("ORTHO") + elasticityType = OrthoLinearElasticModel +CASE ("TRANS") + elasticityType = TransLinearElasticModel +END SELECT + +!> READ isPlaneStrain +dsetname = TRIM(group)//"/isPlaneStrain" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=isPlaneStrain) +ELSE + isPlaneStrain = .FALSE. +END IF + +!> READ isPlaneStress +dsetname = TRIM(group)//"/isPlaneStress" +IF (hdf5%pathExists(dsetname%chars())) THEN + CALL hdf5%READ(dsetname=dsetname%chars(), vals=isPlaneStress) +ELSE + isPlaneStress = .FALSE. +END IF + +IF (elasticityType .EQ. IsoLinearElasticModel) THEN + dsetname = TRIM(group)//"/PoissonRatio" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset PoissonRatio should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=PoissonRatio) + END IF + + dsetname = TRIM(group)//"/YoungsModulus" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset YoungsModulus should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=YoungsModulus) + END IF + + dsetname = TRIM(group)//"/ShearModulus" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset ShearModulus should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=ShearModulus) + END IF + + dsetname = TRIM(group)//"/lambda" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset lambda should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=lambda) + END IF +ELSE + dsetname = TRIM(group)//"/C" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset C should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=C) + END IF + dsetname = TRIM(group)//"/invC" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & 'The dataset invC should be present') + ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=invC) + END IF +END IF + +CALL FPL_INIT(); CALL param%initiate() + +CALL SetLinearPoroElasticModelParam(param=param, & + & elasticityType=elasticityType, isPlaneStrain=isPlaneStrain, & + & isPlaneStress=isPlaneStress, PoissonRatio=PoissonRatio, & + & YoungsModulus=YoungsModulus, ShearModulus=ShearModulus, & + & lambda=lambda, C=C, invC=invC) + +CALL obj%initiate(param) + +CALL param%DEALLOCATE(); CALL FPL_FINALIZE() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import') +#endif +END PROCEDURE lpem_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_Export +CHARACTER(*), PARAMETER :: myName = "lpem_Export" +TYPE(String) :: dsetname, strval + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + +IF (.NOT. obj%isInitiated()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The object is not initiated, initiate first!') +END IF + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file is not opened') +END IF + +IF (.NOT. hdf5%isWrite()) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file does not have write permission') +END IF + +!> WRITE name +dsetname = TRIM(group)//"/name" +strval = obj%GetName() +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) +strval = "" + +!> WRITE elasticityType +dsetname = TRIM(group)//"/elasticityType" +SELECT CASE (obj%elasticityType) +CASE (IsoLinearElasticModel) + strval = "ISO" +CASE (AnisoLinearElasticModel) + strval = "ANISO" +CASE (OrthoLinearElasticModel) + strval = "ORTHO" +CASE (TransLinearElasticModel) + strval = "TRANS" +END SELECT +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) + +!> WRITE isPlaneStrain +dsetname = TRIM(group)//"/isPlaneStrain" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isPlaneStrain()) + +!> WRITE isPlaneStress +dsetname = TRIM(group)//"/isPlaneStress" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isPlaneStress()) + +!> C and invC +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + dsetname = TRIM(group)//"/PoissonRatio" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%nu) + dsetname = TRIM(group)//"/YoungsModulus" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%E) + dsetname = TRIM(group)//"/ShearModulus" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%G) + dsetname = TRIM(group)//"/lambda" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%lambda) + dsetname = TRIM(group)//"/C" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%C) + dsetname = TRIM(group)//"/invC" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%invC) +ELSE + dsetname = TRIM(group)//"/C" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%C) + dsetname = TRIM(group)//"/invC" + CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%invC) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//"::"//myName//" - "// & + & "[END] Export()") +#endif +END PROCEDURE lpem_Export + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_Display + LOGICAL( LGT ) :: isPlaneStrain + LOGICAL( LGT ) :: isPlaneStress + +CALL Display(TRIM(msg), unitNo=unitNo) +CALL Display(obj%isInitiated(), "isInitiated: ", unitNo=unitNo) +IF (.NOT. obj%isInitiated()) THEN + RETURN +END IF + +CALL Display("name: "//myPrefix, unitNo=unitNo) +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + CALL Display("elasticityType: IsoLinearElasticModel", unitNo=unitNo) +ELSE IF (obj%elasticityType .EQ. AnisoLinearElasticModel) THEN + CALL Display("elasticityType: AnisoLinearElasticModel", unitNo=unitNo) +ELSE IF (obj%elasticityType .EQ. OrthoLinearElasticModel) THEN + CALL Display("elasticityType: OrthoLinearElasticModel", unitNo=unitNo) +ELSE IF (obj%elasticityType .EQ. TransLinearElasticModel) THEN + CALL Display("elasticityType: TransLinearElasticModel", unitNo=unitNo) +ELSE + CALL Display("elasticityType: Unknown", unitNo=unitNo) +END IF + +isPlaneStrain = obj%isPlaneStrain() +isPlaneStress = obj%isPlaneStress() + +CALL Display(isPlaneStress, "isPlaneStress: ", unitNo=unitNo) +CALL Display(isPlaneStrain, "isPlaneStrain: ", unitNo=unitNo) + +IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN + + CALL Display(obj%nu, "Poisson ratio: ", unitNo=unitNo) + CALL Display(obj%G, "Shear modulus: ", unitNo=unitNo) + CALL Display(obj%E, "Youngs modulus: ", unitNo=unitNo) + CALL Display(obj%lambda, "Lambda: ", unitNo=unitNo) + + IF (isPlaneStress .OR. isPlaneStrain) THEN + CALL Display(obj%C(1:3, 1:3), "Tangent matrix: ", & + & unitNo=unitNo) + CALL Display(obj%invC(1:3, 1:3), "Compliance matrix: ", & + & unitNo=unitNo) + ELSE + CALL Display(obj%C, "Tangent matrix: ", & + & unitNo=unitNo) + CALL Display(obj%invC, "Compliance matrix: ", & + & unitNo=unitNo) + END IF + +ELSE + + CALL Display(obj%C, "Tangent matrix: ", unitNo=unitNo) + CALL Display(obj%invC, "Compliance matrix: ", unitNo=unitNo) + +END IF + +END PROCEDURE lpem_Display + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE IOMethods diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@SetMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@SetMethods.F90 new file mode 100644 index 000000000..09dadb5e9 --- /dev/null +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@SetMethods.F90 @@ -0,0 +1,36 @@ +! 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(LinearPoroElasticModel_Class) SetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_SetParam +IF (PRESENT(elasticityType)) obj%elasticityType = elasticityType +IF (PRESENT(nu)) obj%nu = nu +IF (PRESENT(G)) obj%G = G +IF (PRESENT(youngsModulus)) obj%E = youngsModulus +IF (PRESENT(lambda)) obj%lambda = lambda +IF (PRESENT(C)) obj%C = C +IF (PRESENT(invC)) obj%invC = invC +END PROCEDURE lpem_SetParam + +END SUBMODULE SetMethods diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@getMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@getMethods.F90 new file mode 100644 index 000000000..cb6235ebb --- /dev/null +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@getMethods.F90 @@ -0,0 +1,71 @@ +! 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(LinearPoroElasticModel_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! lpem_GetElasticParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetElasticParam +IF (PRESENT(PoissonRatio)) PoissonRatio = obj%nu +IF (PRESENT(ShearModulus)) ShearModulus = obj%G +IF (PRESENT(YoungsModulus)) YoungsModulus = obj%E +IF (PRESENT(lambda)) lambda = obj%lambda +END PROCEDURE lpem_GetElasticParam + +!---------------------------------------------------------------------------- +! lpem_GetC +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetC +C = obj%C +END PROCEDURE lpem_GetC + +!---------------------------------------------------------------------------- +! lpem_GetInvC +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetInvC +InvC = obj%InvC +END PROCEDURE lpem_GetInvC + +!---------------------------------------------------------------------------- +! GetElasticityType +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetElasticityType +ans = obj%elasticityType +END PROCEDURE lpem_GetElasticityType + +!---------------------------------------------------------------------------- +! GetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetParam +IF (PRESENT(elasticityType)) elasticityType = obj%elasticityType +IF (PRESENT(nu)) nu = obj%nu +IF (PRESENT(G)) G = obj%G +IF (PRESENT(youngsModulus)) youngsModulus = obj%E +IF (PRESENT(lambda)) lambda = obj%lambda +IF (PRESENT(C)) C = obj%C +IF (PRESENT(invC)) invC = obj%invC +END PROCEDURE lpem_GetParam + +END SUBMODULE GetMethods From 72400125758b6064fa7ffc006085dbbc72f9c638 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:42:55 +0900 Subject: [PATCH 090/117] Adding MaterialFactory --- src/submodules/MaterialFactory/CMakeLists.txt | 22 ++++ .../src/MaterialFactory@Methods.F90 | 123 ++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 src/submodules/MaterialFactory/CMakeLists.txt create mode 100644 src/submodules/MaterialFactory/src/MaterialFactory@Methods.F90 diff --git a/src/submodules/MaterialFactory/CMakeLists.txt b/src/submodules/MaterialFactory/CMakeLists.txt new file mode 100644 index 000000000..959420f35 --- /dev/null +++ b/src/submodules/MaterialFactory/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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}/MaterialFactory@Methods.F90 +) \ No newline at end of file diff --git a/src/submodules/MaterialFactory/src/MaterialFactory@Methods.F90 b/src/submodules/MaterialFactory/src/MaterialFactory@Methods.F90 new file mode 100644 index 000000000..257bf98ed --- /dev/null +++ b/src/submodules/MaterialFactory/src/MaterialFactory@Methods.F90 @@ -0,0 +1,123 @@ +! 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 +! + +!> authors: Vikas Sharma, Ph. D. +! date: 25 Aug 2021 +! summary: This module is a factory modules for the material module + +SUBMODULE(MaterialFactory) Methods +USE easifemMaterials +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SolidMechanicsModelFactory +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SolidMechanicsModelFactory +CHARACTER(*), PARAMETER :: myName = "SolidMechanicsModelFactory" +SELECT CASE (TRIM(name)) +CASE ("LinearElasticModel", "linearElasticModel") + ALLOCATE (LinearElasticModel_ :: ans) +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Currently LinearElasticModel as SolidMechanicsModel is & + & avaiable, we are working on others.') +END SELECT +END PROCEDURE SolidMechanicsModelFactory + +!---------------------------------------------------------------------------- +! FluidMechanicsModelFactory +!---------------------------------------------------------------------------- + +MODULE PROCEDURE FluidMechanicsModelFactory +CHARACTER(*), PARAMETER :: myName = "FluidMechanicsModelFactory" +SELECT CASE (TRIM(name)) +CASE ("NewtonianFluidModel", "newtonianFluidModel") + ALLOCATE (NewtonianFluidModel_ :: ans) +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Unknown fluid mechanica model, currently, easifemMaterials & + & supports only the NewtonianFluidModel,we are working on others.') +END SELECT +END PROCEDURE FluidMechanicsModelFactory + +!---------------------------------------------------------------------------- +! PoroMechanicsModelFactory +!---------------------------------------------------------------------------- + +MODULE PROCEDURE PoroMechanicsModelFactory +CHARACTER(*), PARAMETER :: myName = "PoroMechanicsModelFactory" +SELECT CASE (TRIM(name)) +CASE ("LinearPoroElasticModel", "linearPoroElasticModel") + ALLOCATE (LinearPoroElasticModel_ :: ans) +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Currently LinearPoroElasticModel as PoroMechanicsModel_ is & + & avaiable, we are working on others.') +END SELECT +END PROCEDURE PoroMechanicsModelFactory + +!---------------------------------------------------------------------------- +! SolidMaterialFactory +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SolidMaterialFactory +CHARACTER(*), PARAMETER :: myName = "SolidMaterialFactory" +SELECT CASE (TRIM(name)) +CASE ("SolidMaterial", "solidMaterial") + ALLOCATE (SolidMaterial_ :: ans) +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Cannot find the material name. Currently, only SolidMaterial is & + & avaiable, we are working on others.') +END SELECT +END PROCEDURE SolidMaterialFactory + +!---------------------------------------------------------------------------- +! FluidMaterialFactory +!---------------------------------------------------------------------------- + +MODULE PROCEDURE FluidMaterialFactory +CHARACTER(*), PARAMETER :: myName = "FluidMaterialFactory" +SELECT CASE (TRIM(name)) +CASE ("FluidMaterial", "fluidMaterial") + ALLOCATE (FluidMaterial_ :: ans) +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Cannot find the material name. Currently, only fluidMaterial is & + & avaiable, we are working on others.') +END SELECT +END PROCEDURE FluidMaterialFactory + +!---------------------------------------------------------------------------- +! PorousMaterialFactory +!---------------------------------------------------------------------------- + +MODULE PROCEDURE PorousMaterialFactory +CHARACTER(*), PARAMETER :: myName = "PorousMaterialFactory" +SELECT CASE (TRIM(name)) +CASE ("PorousMaterial", "porousMaterial") + ALLOCATE (PorousMaterial_ :: ans) +CASE DEFAULT + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'Cannot find the material name. Currently, only porousMaterial is & + & avaiable, we are working on others.') +END SELECT +END PROCEDURE PorousMaterialFactory + +END SUBMODULE Methods From ed585e663cb5e6de1827c4fac8af939c3330edef Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:43:08 +0900 Subject: [PATCH 091/117] Adding NewtonianFluidModel --- .../NewtonianFluidModel/CMakeLists.txt | 25 +++ ...ianFluidModel_Class@ConstructorMethods.F90 | 94 +++++++++++ .../NewtonianFluidModel_Class@IOMethods.F90 | 148 ++++++++++++++++++ .../NewtonianFluidModel_Class@getMethods.F90 | 59 +++++++ .../NewtonianFluidModel_Class@setMethods.F90 | 41 +++++ 5 files changed, 367 insertions(+) create mode 100644 src/submodules/NewtonianFluidModel/CMakeLists.txt create mode 100644 src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@ConstructorMethods.F90 create mode 100644 src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@IOMethods.F90 create mode 100644 src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@getMethods.F90 create mode 100644 src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@setMethods.F90 diff --git a/src/submodules/NewtonianFluidModel/CMakeLists.txt b/src/submodules/NewtonianFluidModel/CMakeLists.txt new file mode 100644 index 000000000..bfe1ef28e --- /dev/null +++ b/src/submodules/NewtonianFluidModel/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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}/NewtonianFluidModel_Class@ConstructorMethods.F90 + ${src_path}/NewtonianFluidModel_Class@IOMethods.F90 + ${src_path}/NewtonianFluidModel_Class@GetMethods.F90 + ${src_path}/NewtonianFluidModel_Class@SetMethods.F90 +) diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@ConstructorMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..8215cdecc --- /dev/null +++ b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@ConstructorMethods.F90 @@ -0,0 +1,94 @@ +! 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(NewtonianFluidModel_Class) ConstructorMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetNewtonianFluidModelParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetNewtonianFluidModelParam +INTEGER(I4B) :: ierr +ierr = param%Set(key=myprefix//"/name", & + & VALUE="NewtonianFluidModel") +ierr = param%Set(key=myprefix//"/dynamicViscosity", & + & VALUE=DynamicViscosity) +END PROCEDURE SetNewtonianFluidModelParam + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "nfm_CheckEssentialParam" + +IF (.NOT. param%isPresent(key=myprefix//"/dynamicViscosity")) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & myprefix//'/dynamicViscosity should be present in param') +END IF + +IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & myprefix//'/name should be present in param') +END IF + +END PROCEDURE nfm_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_Initiate +CHARACTER(*), PARAMETER :: myName = "nfm_Initiate" +INTEGER(I4B) :: ierr + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +CALL obj%CheckEssentialParam(param) +CALL obj%SetIsInitiated(.TRUE.) +CALL obj%SetName(myprefix) +ierr = param%Get(key=myprefix//"/dynamicViscosity", VALUE=obj%mu) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif +END PROCEDURE nfm_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_Deallocate +obj%mu = 0.0 +CALL AbstractMaterialModelDeallocate(obj) +END PROCEDURE nfm_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_Final +CALL obj%DEALLOCATE() +END PROCEDURE nfm_Final + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@IOMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@IOMethods.F90 new file mode 100644 index 000000000..6eb1993d6 --- /dev/null +++ b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@IOMethods.F90 @@ -0,0 +1,148 @@ +! 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 + +!> authors: Vikas Sharma, Ph. D. +! date: 27 Aug 2021 +! summary: This submodule contains input-output methods + +SUBMODULE(NewtonianFluidModel_Class) IOMethods +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_Import +CHARACTER(*), PARAMETER :: myName = "nfm_Import" +TYPE(String) :: dsetname, strval +REAL(DFP) :: DynamicViscosity +TYPE(ParameterList_) :: param + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +IF (obj%isInitiated()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The object is already initiated, deallocate first!') +END IF + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file is not opened') +END IF + +IF (.NOT. hdf5%isRead()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file does not have read permission') +END IF + +!> READ name +dsetname = TRIM(group)//"/name" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG] The dataset name should be present') +END IF +CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) +CALL obj%SetName(strval%chars()) +strval = "" +!> READ DynamicViscosity + +dsetname = TRIM(group)//"/dynamicViscosity" +IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'The dataset dynamicViscosity should be present') +ELSE + CALL hdf5%READ(dsetname=dsetname%chars(), vals=DynamicViscosity) +END IF + +CALL param%initiate() +CALL SetNewtonianFluidModelParam(param=param, & + & DynamicViscosity=DynamicViscosity) +CALL obj%initiate(param) +CALL param%DEALLOCATE() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif +END PROCEDURE nfm_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_Export +CHARACTER(*), PARAMETER :: myName = "nfm_Export" +TYPE(String) :: dsetname, strval +!> main + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + +IF (.NOT. obj%isInitiated()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: The object is not initiated, initiate first!') +END IF + +IF (.NOT. hdf5%isOpen()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file is not opened') +END IF + +IF (.NOT. hdf5%isWrite()) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONFIG ERROR] :: HDF5 file does not have write permission') +END IF + +dsetname = TRIM(group)//"/name" +strval = obj%GetName() +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) +strval = "" + +dsetname = TRIM(group)//"/dynamicViscosity" +CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%Mu) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif +END PROCEDURE nfm_Export + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_Display +CALL Display(TRIM(msg), unitNo=unitNo) +CALL Display(obj%isInitiated(), "isInitiated: ", unitNo=unitNo) +IF (.NOT. obj%isInitiated()) THEN + RETURN +END IF +CALL Display("name : NewtonianFluidModel", unitNo=unitNo) +CALL Display(obj%mu, "dynamicViscosity : ", unitNo=unitNo) +END PROCEDURE nfm_Display + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE IOMethods diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@getMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@getMethods.F90 new file mode 100644 index 000000000..d3aeb3806 --- /dev/null +++ b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@getMethods.F90 @@ -0,0 +1,59 @@ +! 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(NewtonianFluidModel_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetDynamicViscosity +DynamicViscosity = obj%Mu +END PROCEDURE nfm_GetDynamicViscosity + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetModelParameters +INTEGER(I4B) :: ierr +IF (obj%isInitiated()) THEN + ierr = param%set(key=myprefix//"/name", & + & VALUE="NewtonianFluidModel") + ierr = param%set(key=myprefix//"/dynamicViscosity", VALUE=obj%Mu) +END IF +END PROCEDURE nfm_GetModelParameters + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetPrefix +ans = myprefix +END PROCEDURE nfm_GetPrefix + +!---------------------------------------------------------------------------- +! GetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetParam +IF (PRESENT(dynamicViscosity)) dynamicViscosity = obj%mu +END PROCEDURE nfm_GetParam + +END SUBMODULE GetMethods diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@setMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@setMethods.F90 new file mode 100644 index 000000000..31d88ab4c --- /dev/null +++ b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@setMethods.F90 @@ -0,0 +1,41 @@ +! 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(NewtonianFluidModel_Class) SetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_SetModelParameters +INTEGER(I4B) :: ierr +IF (param%IsPresent(key=myprefix//"/dynamicViscosity")) THEN + ierr = param%Get(key=myprefix//"/dynamicViscosity", VALUE=obj%mu) +END IF +END PROCEDURE nfm_SetModelParameters + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_SetParam +IF (PRESENT(dynamicViscosity)) obj%mu = dynamicViscosity +END PROCEDURE nfm_SetParam + +END SUBMODULE SetMethods From d5221224284c3114672730be492603f39160706d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:43:17 +0900 Subject: [PATCH 092/117] Adding oldMaterialLibrary --- .../Material/Material_Class@Methods_old.f90 | 96 +++++ .../Material/Material_Class@Soil.f90 | 380 ++++++++++++++++++ .../SFCCModel_Class@ExpModel.f90 | 97 +++++ .../SFCCModel_Class@User.f90 | 13 + .../ThermCondModel_Class@Johansen.f90 | 147 +++++++ .../ThermCondModel_Class@User.f90 | 22 + .../VolHeatCapModel_Class@MixModel.f90 | 76 ++++ .../VolHeatCapModel_Class@User.f90 | 26 ++ 8 files changed, 857 insertions(+) create mode 100644 src/submodules/oldLibrary/Material/Material_Class@Methods_old.f90 create mode 100644 src/submodules/oldLibrary/Material/Material_Class@Soil.f90 create mode 100644 src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@ExpModel.f90 create mode 100644 src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@User.f90 create mode 100644 src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@Johansen.f90 create mode 100644 src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@User.f90 create mode 100644 src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@MixModel.f90 create mode 100644 src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@User.f90 diff --git a/src/submodules/oldLibrary/Material/Material_Class@Methods_old.f90 b/src/submodules/oldLibrary/Material/Material_Class@Methods_old.f90 new file mode 100644 index 000000000..98ae67ecd --- /dev/null +++ b/src/submodules/oldLibrary/Material/Material_Class@Methods_old.f90 @@ -0,0 +1,96 @@ +SUBMODULE(Material_Class) Methods +!! This submodule implements the type bound procedure of [[material_]] +USE BaseMethod +IMPLICIT NONE + +CONTAINS + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_initiate + IF( ALLOCATED( Obj % Props ) ) DEALLOCATE( Obj % Props ) + ALLOCATE( Obj % Props( tprop ) ) +END PROCEDURE mat_initiate + +!---------------------------------------------------------------------------- +! Append +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_append + CALL Append( Obj % Props, KeyValObj ) +END PROCEDURE mat_append + +!---------------------------------------------------------------------------- +! Size +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_size + IF( ALLOCATED( Obj % Props ) ) THEN + Ans = SIZE( Obj % Props ) + ELSE + Ans = 0 + END IF +END PROCEDURE mat_size + +!---------------------------------------------------------------------------- +! Property +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_get_prop + + INTEGER( I4B ) :: i + + i = Obj % Props .INDEX. key + + IF( i .NE. 0 ) THEN + Ans = Obj % Props( i ) + ELSE + Ans = KeyValue( 'NONE', 0 ) + END IF + +END PROCEDURE mat_get_prop + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_deallocate + IF( ALLOCATED( Obj % Props ) ) DEALLOCATE( Obj % Props ) +END PROCEDURE mat_deallocate + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_display + INTEGER( I4B ) :: i + i =stdout + IF ( PRESENT( unitno ) ) i = unitno + IF( LEN_TRIM( msg ) .NE. 0 ) WRITE( I, "(A)" ) TRIM( msg ) + CALL Display( Obj % Props, "", i ) + CALL Dashline( Unitno = i ) +END PROCEDURE mat_display + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mat_display_vec + INTEGER( I4B ) :: i, j + i =stdout + IF ( PRESENT( unitno ) ) i = unitno + IF( LEN_TRIM( msg ) .NE. 0 ) WRITE( I, "(A)" ) TRIM( msg ) + WRITE( I, "(A, I4)" ) "Total Materials :: ", SIZE( Obj ) + + DO j = 1, SIZE( Obj ) + CALL Display( Obj( j ) % Props, "", i ) + END DO +END PROCEDURE mat_display_vec + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE Methods \ No newline at end of file diff --git a/src/submodules/oldLibrary/Material/Material_Class@Soil.f90 b/src/submodules/oldLibrary/Material/Material_Class@Soil.f90 new file mode 100644 index 000000000..56118b16e --- /dev/null +++ b/src/submodules/oldLibrary/Material/Material_Class@Soil.f90 @@ -0,0 +1,380 @@ +SUBMODULE(Material_Class) Soil +USE BaseMethod +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Soil_display + INTEGER( I4B ) :: I + + IF( PRESENT( UnitNo ) ) THEN + I = UnitNo + ELSE + I = stdout + END IF + + IF( LEN_TRIM( msg ) .NE. 0 ) THEN + WRITE( I, "(A)" ) TRIM( msg ) + END IF + + CALL Display( STATE_NAME(Obj%State), "State :: ", UnitNo = I ) + CALL Display( SOILTYPE_NAME(Obj%SoilType), "SoilType :: ", UnitNo = I ) + CALL Display( Obj%Gravel, "Gravel :: ", UnitNo = I ) + CALL Display( Obj%Sand, "Sand :: ", UnitNo = I ) + CALL Display( Obj%Silt, "Silt :: ", UnitNo = I ) + CALL Display( Obj%Clay, "Clay :: ", UnitNo = I ) + CALL Display( Obj%OrganicMatter, "OrganicMatter :: ", UnitNo = I ) + CALL Display( Obj%SpecificGravity, "SpecificGravity :: ", UnitNo = I ) + CALL Display( Obj%DryDensity, "DryDensity :: ", UnitNo = I ) + CALL Display( Obj%Gravimetric_Moisture, "Gravimetric_Moisture :: ", & + & UnitNo = I ) + CALL Display( Obj%Porosity, "Porosity :: ", UnitNo = I ) + CALL Display( MINERAL_NAME(MINERAL_QUARTZ), "Quartz :: ", UnitNo = I ) + CALL Display( THERMCONDMODEL_NAME(Obj%ThermCond_Model), & + & "ThermCondModel :: ", UnitNo = I ) + CALL Display( VOLHEATCAPMODEL_NAME(Obj%volHeatCap_Model), & + & "volHeatCapModel :: ", UnitNo = I ) + CALL Display( SFCCMODEL_NAME(Obj%SFCC_Model), & + & "SFCC Model :: ", UnitNo = I ) +END PROCEDURE Soil_display + +!---------------------------------------------------------------------------- +! Soil +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Soil_Constructor + CHARACTER( LEN = 3 ) :: JohansenCase + + IF( PRESENT( State ) ) THEN + Ans%State= State + ELSE + Ans%State= TypeSoil%State + END IF + + IF( PRESENT( SoilType ) ) THEN + Ans%SoilType = SoilType + ELSE + Ans%SoilType = TypeSoil%SoilType + END IF + + IF( PRESENT( Gravel ) ) THEN + Ans%Gravel = Gravel + ELSE + Ans%Gravel = TypeSoil%Gravel + END IF + + IF( PRESENT( Sand ) ) THEN + Ans%Sand = Sand + ELSE + Ans%Sand = TypeSoil%Sand + END IF + + IF( PRESENT( Silt ) ) THEN + Ans%Silt = Silt + ELSE + Ans%Silt = TypeSoil%Silt + END IF + + IF( PRESENT( Clay ) ) THEN + Ans%Clay = Clay + ELSE + Ans%Clay = TypeSoil%Clay + END IF + + IF( PRESENT( OrganicMatter ) ) THEN + Ans%OrganicMatter = OrganicMatter + ELSE + Ans%OrganicMatter = TypeSoil%OrganicMatter + END IF + + IF( PRESENT( SpecificGravity ) ) THEN + Ans%SpecificGravity = SpecificGravity + ELSE + Ans%SpecificGravity = TypeSoil%SpecificGravity + END IF + + IF( PRESENT( DryDensity ) ) THEN + Ans%DryDensity = DryDensity + ELSE + Ans%DryDensity = TypeSoil%DryDensity + END IF + + IF( PRESENT( Gravimetric_Moisture ) ) THEN + Ans%Gravimetric_Moisture = Gravimetric_Moisture + ELSE + Ans%Gravimetric_Moisture = TypeSoil%Gravimetric_Moisture + END IF + + IF( PRESENT( Porosity ) ) THEN + Ans%Porosity = Porosity + Ans%voidRatio = Porosity/(1-Porosity) + ELSE + Ans%Porosity = TypeSoil%Porosity + END IF + + IF( PRESENT( voidRatio ) ) THEN + Ans%voidRatio = voidRatio + Ans%Porosity = voidRatio/(1 + voidRatio) + ELSE + Ans%voidRatio = TypeSoil%voidRatio + END IF + + IF( PRESENT( volFrac_solid ) ) THEN + Ans%volFrac_solid = volFrac_solid + END IF + + IF( PRESENT( volFrac_water ) ) THEN + Ans%volFrac_water = volFrac_water + END IF + + IF( PRESENT( volFrac_ice ) ) THEN + Ans%volFrac_ice = volFrac_ice + END IF + + IF( PRESENT( volFrac_air ) ) THEN + Ans%volFrac_air = volFrac_air + END IF + + IF( PRESENT( Minerals ) ) THEN + Ans%Minerals( 1:SIZE(Minerals) ) = Minerals + ELSE + Ans%Minerals = TypeSoil%Minerals + END IF + + !! Setting thermal properties + IF( PRESENT( ThermCondModel ) ) THEN + Ans%ThermCond_Model = ThermCondModel + + !! Select thermal conductivity models + SELECT CASE( ThermCondModel ) + !! User defined thermal conductivity model + CASE( User_ThermCond ) + + IF( .NOT. PRESENT( UserThermCond ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " UserThemCond procedure should be given") + STOP + END IF + + Ans%ThermCondModel => UserThermCond_Pointer() + Ans%ThermCondModel%getValue => UserThermCond + + !! Johansen thermal conductivity model + CASE( Johansen_ThermCond ) + + IF( PRESENT( Lambda_Sat ) ) THEN + JohansenCase(1:1) = 'S' + ELSE + JohansenCase(1:1) = 's' + END IF + + IF( PRESENT( Lambda_Dry ) ) THEN + JohansenCase(2:2) = 'D' + ELSE + JohansenCase(2:2) = 'd' + END IF + + IF( PRESENT( Lambda_e ) ) THEN + JohansenCase(3:3) = 'E' + ELSE + JohansenCase(3:3) = 'e' + END IF + + SELECT CASE( JohansenCase ) + CASE( 'SDE' ) + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_Sat = Lambda_Sat, Lambda_Dry = Lambda_Dry, & + & Lambda_e = Lambda_e, Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'SDe') + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_Sat = Lambda_Sat, Lambda_Dry = Lambda_Dry,& + & Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'SdE') + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_Sat = Lambda_Sat, & + & Lambda_e = Lambda_e, Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'Sde') + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_Sat = Lambda_Sat, & + & Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'sDE' ) + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_Dry = Lambda_Dry, & + & Lambda_e = Lambda_e, Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'sDe') + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_Dry = Lambda_Dry, & + & Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'sdE') + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Lambda_e = Lambda_e, Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + CASE( 'sde') + Ans%ThermCondModel => JohansenThermCond_Pointer( & + & Gamma_d=Ans%DryDensity, & + & QuartzContent = Ans%Minerals(Ans%Quartz), & + & SoilState = Ans%State, SoilType = Ans%SoilType ) + END SELECT + + !! Constant thermal conductivity model + CASE( Constant_ThermCond ) + IF( .NOT. PRESENT( ThermCondVal ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " ThermCondVal should be given") + STOP + END IF + + Ans%ThermCondModel => UserThermCond_Pointer() + Ans%ThermCondModel%ConstThermCondVal= ThermCondVal + END SELECT + END IF + + IF( PRESENT( volHeatCapModel ) ) THEN + Ans%volHeatCap_Model = volHeatCapModel + + SELECT CASE( volHeatCapModel ) + CASE( CONSTANT_VOLHEATCAP ) + + IF( .NOT. PRESENT( volHeatCapVal ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " volHeatCap should be given") + STOP + END IF + + Ans%volHeatCapModel => UserVolHeatCap_Pointer() + Ans%volHeatCapModel%ConstVolHeatCapVal= volHeatCapVal + IF( PRESENT( volHeatCap_solid ) ) THEN + Ans%VolHeatCapModel%volHeatCap_solid = volHeatCap_solid + END IF + + CASE( USER_VOLHEATCAP ) + + IF( .NOT. PRESENT( UserVolHeatCap ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " UserVolHeatCap procedure should be given") + STOP + END IF + + Ans%VolHeatCapModel => UserVolHeatCap_Pointer() + Ans%VolHeatCapModel%getValue => UserVolHeatCap + IF( PRESENT( volHeatCap_solid ) ) THEN + Ans%VolHeatCapModel%volHeatCap_solid = volHeatCap_solid + END IF + + CASE( MIX_VOLHEATCAP ) + + IF( PRESENT( volHeatCap_solid ) ) THEN + Ans%volHeatCapModel => MixVolHeatCap_Pointer( & + & volHeatCap_solid = volHeatCap_solid, SoilState = Ans%State ) + ELSE + Ans%volHeatCapModel => MixVolHeatCap_Pointer( SoilState = Ans%State ) + END IF + + END SELECT + END IF + + + IF( PRESENT( SFCCModel ) ) THEN + Ans%SFCC_Model = SFCCModel + + SELECT CASE( SFCCModel ) + CASE( User_SFCC ) + + IF( .NOT. PRESENT( UserSFCC_Value ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " UserSFCC_Value procedure should be given") + STOP + END IF + + IF( .NOT. PRESENT( UserSFCC_Slope ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " UserSFCC_Slope procedure should be given") + STOP + END IF + + Ans%SFCCModel => UserSFCC_Pointer() + Ans%SFCCModel%getValue => UserSFCC_Value + Ans%SFCCModel%getSlope => UserSFCC_Slope + + CASE( EXP_SFCC ) + IF( .NOT. PRESENT( volFrac_water ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " volFrac_water should be given") + STOP + END IF + + IF( .NOT. PRESENT( SFCC_Theta_r ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " SFCC_Theta_r should be given") + STOP + END IF + + IF( .NOT. PRESENT( SFCC_Temp_l ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " SFCC_Temp_l should be given") + STOP + END IF + + IF( .NOT. PRESENT( SFCC_Temp_s ) ) THEN + CALL Display( "ERROR:: In File "// TRIM( __FILE__ ) ) + CALL Display( " in function Soil_Constructor()" ) + CALL Display( " Line Number:: " // TRIM( INT2STR(__LINE__) ) ) + CALL Display( " SFCC_Temp_s should be given") + STOP + END IF + + IF( PRESENT( SFCC_Coeff ) ) THEN + Ans%SFCCModel => ExpSFCC_Pointer(& + & Theta_r = SFCC_Theta_r, & + & Theta_w = volFrac_water, & + & Temp_l = SFCC_Temp_l, & + & Temp_s = SFCC_Temp_s, & + & Coeff = SFCC_Coeff ) + ELSE + Ans%SFCCModel => ExpSFCC_Pointer(& + & Theta_r = SFCC_Theta_r, & + & Theta_w = volFrac_water, & + & Temp_l = SFCC_Temp_l, & + & Temp_s = SFCC_Temp_s ) + END IF + + END SELECT + END IF + +END PROCEDURE Soil_Constructor + +END SUBMODULE Soil \ No newline at end of file diff --git a/src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@ExpModel.f90 b/src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@ExpModel.f90 new file mode 100644 index 000000000..5a4891509 --- /dev/null +++ b/src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@ExpModel.f90 @@ -0,0 +1,97 @@ +SUBMODULE(SFCCModel_Class) ExpModel + IMPLICIT NONE + CONTAINS + +!---------------------------------------------------------------------------- +! ExpSFCC_Pointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ExpSFCC_Pointer + ALLOCATE( Ans ) + Ans%Theta_r = Theta_r + Ans%Theta_w = Theta_w + Ans%Temp_l = Temp_l + Ans%Temp_s = Temp_s + IF( PRESENT( Coeff ) ) Ans%Coeff=Coeff + Ans%getValue => ExpSFCC_get_val + Ans%getSlope => ExpSFCC_get_slope + Ans%PhaseInfo => ExpSFCC_PhaseInfo +END PROCEDURE ExpSFCC_Pointer + +!---------------------------------------------------------------------------- +! getValue +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ExpSFCC_get_val + REAL( DFP ) :: c + SELECT TYPE( Obj ) + CLASS IS( ExpSFCC_ ) + IF( Temp .GE. Obj%Temp_l ) THEN + Ans=Obj%Theta_w + RETURN + END IF + + IF( Temp .LE. Obj%Temp_s ) THEN + Ans = Obj%Theta_r + RETURN + END IF + + c = -Obj%Coeff*((Temp-Obj%Temp_l)/(Obj%Temp_s-Obj%Temp_l))**2 + Ans = Obj%Theta_r + (Obj%Theta_w-Obj%Theta_r)*EXP(c) + END SELECT +END PROCEDURE ExpSFCC_get_val + +!---------------------------------------------------------------------------- +! getSlope +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ExpSFCC_get_slope + REAL( DFP ) :: c, b + + SELECT TYPE( Obj ) + CLASS IS( ExpSFCC_ ) + IF( Temp .GE. Obj%Temp_l ) THEN + Ans=0.0_DFP + RETURN + END IF + + IF( Temp .LE. Obj%Temp_s ) THEN + Ans = 0.0_DFP + RETURN + END IF + + b = -2.0*Obj%Coeff * (Temp-Obj%Temp_l)*(Obj%Theta_w - Obj%Theta_r) & + & / (Obj%Temp_s-Obj%Temp_l)**2 + + c = -Obj%Coeff*((Temp-Obj%Temp_l)/(Obj%Temp_s-Obj%Temp_l))**2 + + Ans = b*EXP(c) + END SELECT +END PROCEDURE ExpSFCC_get_slope + +!---------------------------------------------------------------------------- +! PhaseInfo +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ExpSFCC_PhaseInfo + SELECT TYPE( Obj ) + CLASS IS( ExpSFCC_ ) + IF( ABS(Temp - Obj%Temp_l) .LE. 1.0E-10 .OR. Temp .GE. Obj%Temp_l ) THEN + Ans = 'L' + RETURN + END IF + + IF( ABS(Temp - Obj%Temp_s) .LE. 1.0E-10 .OR. Temp .LE. Obj%Temp_s ) THEN + Ans = 'S' + RETURN + END IF + + Ans = 'M' + END SELECT +END PROCEDURE ExpSFCC_PhaseInfo + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE ExpModel \ No newline at end of file diff --git a/src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@User.f90 b/src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@User.f90 new file mode 100644 index 000000000..b62ed32b9 --- /dev/null +++ b/src/submodules/oldLibrary/MaterialProperties/SFCCModel_Class@User.f90 @@ -0,0 +1,13 @@ +SUBMODULE(SFCCModel_Class) User +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! UserSFCC_Pointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE UserSFCC_Pointer + ALLOCATE( Ans ) +END PROCEDURE UserSFCC_Pointer + +END SUBMODULE User \ No newline at end of file diff --git a/src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@Johansen.f90 b/src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@Johansen.f90 new file mode 100644 index 000000000..db6fd3473 --- /dev/null +++ b/src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@Johansen.f90 @@ -0,0 +1,147 @@ +SUBMODULE(ThermCondModel_Class) Johansen +USE stdMaterials +IMPLICIT NONE + +CONTAINS + +!---------------------------------------------------------------------------- +! johansen_constructor_pointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE JohansenThermCond_Pointer + ALLOCATE( Ans ) + IF( PRESENT( Lambda_Sat ) ) THEN + Ans%isLambda_sat_given=.TRUE. + ELSE + Ans%isLambda_sat_given=.FALSE. + END IF + + IF( PRESENT( Lambda_dry ) ) THEN + Ans%isLambda_dry_given=.TRUE. + ELSE + Ans%isLambda_dry_given=.FALSE. + END IF + + IF( PRESENT( Lambda_e ) ) THEN + Ans%isLambda_e_given=.TRUE. + ELSE + Ans%isLambda_e_given=.FALSE. + END IF + + IF( PRESENT( Gamma_d ) ) THEN + Ans%Gamma_d = Gamma_d + END IF + + IF( PRESENT( QuartzContent ) ) THEN + Ans%QuartzContent = QuartzContent + END IF + + IF( PRESENT( SoilType ) ) THEN + Ans%SoilType = SoilType + END IF + + IF( PRESENT( SoilState ) ) THEN + Ans%State=SoilState + END IF + + Ans % getValue => johansen_getval + + IF( .NOT. Ans%isLambda_sat_given ) THEN + IF( Ans%QuartzContent .GT. 0.2_DFP ) THEN + Ans%Lambda_s = (7.7_DFP**Ans%QuartzContent) & + & * (2.0_DFP**(1.0_DFP-Ans%QuartzContent)) + ELSE + Ans%Lambda_s = (7.7_DFP**Ans%QuartzContent) & + & * (3.0_DFP**(1.0_DFP-Ans%QuartzContent)) + END IF + END IF + +END PROCEDURE JohansenThermCond_Pointer + +!---------------------------------------------------------------------------- +! getValue@Johansen +!---------------------------------------------------------------------------- + +MODULE PROCEDURE johansen_getval + REAL( DFP ) :: Lam_w, Lam_i, Lam_sat, Lam_dry, Lam_e + + ! + SELECT TYPE( Obj ) + TYPE IS (JohansenThermCond_) + + ! compute Lambda_sat + SELECT CASE( Obj%SoilType ) + ! Case for peaty soils + CASE( SOIL_PEAT ) + + ! Case for non peaty soils + CASE DEFAULT + + ! Calculate Lambda_sat + IF( Obj%isLambda_sat_given ) THEN + Lam_sat = Obj%Lambda_sat + ELSE + + IF( PRESENT( Temp ) ) THEN + Lam_w = ThermCond_Water(Temp=Temp) + ELSE + Lam_w = ThermCond_Water() + END IF + + IF( Obj%State .EQ. STATE_Unfrozen ) THEN + + Lam_sat = (Obj%Lambda_s**volFrac_solid)& + & *(Lam_w**volFrac_water) + + ELSE + + ! get thermal conductivity of ice + IF( PRESENT( Temp ) ) THEN + Lam_i = ThermCond_Ice(Temp=Temp) + ELSE + Lam_i = ThermCond_Ice() + END IF + + Lam_sat = ( Obj%Lambda_s**volFrac_solid ) & + & * ( Lam_w**volFrac_water ) & + & * ( Lam_i**volFrac_ice ) + END IF + END IF + + ! Calculate Lambda_dry + IF( Obj%isLambda_dry_given ) THEN + Lam_dry = Obj%Lambda_dry + ELSE + Lam_dry = 1.2_DFP * ( 0.135 * Obj%Gamma_d + 64.7_DFP ) & + & / ( 2700.0_DFP - 0.947 * Obj%Gamma_d ) + END IF + + ! Calculate Lambda_e + IF( Obj%isLambda_e_given ) THEN + Lam_e = Obj%Lambda_e + ELSE + IF( Obj%State .EQ. STATE_Frozen ) THEN + Lam_e = volFrac_water/(volFrac_ice+volFrac_air+volFrac_water) + ELSE + IF( Obj%SoilType .EQ. SOIL_FINE_GRAINED) THEN + Lam_e = 1.0_DFP + LOG10(volFrac_water / & + & (volFrac_ice+volFrac_air+volFrac_water)) + ELSE + Lam_e = 1.0_DFP + 0.7_DFP * LOG10(volFrac_water / & + & (volFrac_ice+volFrac_air+volFrac_water)) + END IF + END IF + END IF + + Ans = ( Lam_sat - Lam_dry ) * Lam_e + Lam_dry + + END SELECT + END SELECT + +END PROCEDURE johansen_getval + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE Johansen \ No newline at end of file diff --git a/src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@User.f90 b/src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@User.f90 new file mode 100644 index 000000000..92c18697e --- /dev/null +++ b/src/submodules/oldLibrary/MaterialProperties/ThermCondModel_Class@User.f90 @@ -0,0 +1,22 @@ +SUBMODULE(ThermCondModel_Class) User +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! UserThermCond_Pointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE UserThermCond_Pointer + ALLOCATE( Ans ) + Ans%getValue => UserThermCond_getval +END PROCEDURE UserThermCond_Pointer + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE UserThermCond_getval + Ans = Obj%ConstThermCondVal +END PROCEDURE UserThermCond_getval + +END SUBMODULE User \ No newline at end of file diff --git a/src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@MixModel.f90 b/src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@MixModel.f90 new file mode 100644 index 000000000..ece5f55be --- /dev/null +++ b/src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@MixModel.f90 @@ -0,0 +1,76 @@ +SUBMODULE(VolHeatCapModel_Class) MixModel +USE stdMaterials +IMPLICIT NONE + +CONTAINS + +!---------------------------------------------------------------------------- +! johansen_constructor_pointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE MixVolHeatCap_Pointer + ALLOCATE( Ans ) + + IF( PRESENT( volHeatCap_Solid ) ) THEN + Ans%volHeatCap_solid= volHeatCap_solid + Ans%is_volHeatCap_solid_given = .TRUE. + ELSE + Ans%volHeatCap_solid = volHeatCap_Quartz() + Ans%is_volHeatCap_solid_given = .FALSE. + END IF + + IF( PRESENT( SoilState ) ) THEN + Ans%State = SoilState + ELSE + Ans%State = Ans%Unfrozen + END IF + + Ans % getValue => mixvolheatcap_getval + +END PROCEDURE MixVolHeatCap_Pointer + +!---------------------------------------------------------------------------- +! getValue +!---------------------------------------------------------------------------- + +MODULE PROCEDURE mixvolheatcap_getval + REAL( DFP ) :: c_s, c_i, c_w, c_a + +SELECT TYPE( Obj ) +TYPE IS (MixVolHeatCap_) + + IF( PRESENT( Temp ) ) THEN + c_s = VolHeatCap_Quartz(Temp=Temp) + ELSE + c_s = VolHeatCap_Quartz() + END IF + + IF( PRESENT( Temp ) ) THEN + c_w = VolHeatCap_Water(Temp=Temp) + ELSE + c_w = VolHeatCap_Water() + END IF + + IF( PRESENT( Temp ) ) THEN + c_i = VolHeatCap_Ice(Temp=Temp) + ELSE + c_i = VolHeatCap_Ice() + END IF + + IF( PRESENT( Temp ) ) THEN + c_a = VolHeatCap_Air(Temp=Temp) + ELSE + c_a = VolHeatCap_Air() + END IF + + Ans = VolFrac_solid * c_s + VolFrac_water * c_w + VolFrac_ice * c_i & + & + VolFrac_air * c_a + +END SELECT +END PROCEDURE mixvolheatcap_getval + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE MixModel \ No newline at end of file diff --git a/src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@User.f90 b/src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@User.f90 new file mode 100644 index 000000000..766718fed --- /dev/null +++ b/src/submodules/oldLibrary/MaterialProperties/VolHeatCapModel_Class@User.f90 @@ -0,0 +1,26 @@ +SUBMODULE(VolHeatCapModel_Class) User +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! userVolHeatCap_Pointer +!---------------------------------------------------------------------------- + +MODULE PROCEDURE userVolHeatCap_Pointer + ALLOCATE( Ans ) + Ans%getValue => userVolHeatCap_getval +END PROCEDURE userVolHeatCap_Pointer + +!---------------------------------------------------------------------------- +! userVolHeatCap_getval +!---------------------------------------------------------------------------- + +MODULE PROCEDURE userVolHeatCap_getval + Ans = Obj%ConstVolHeatCapVal +END PROCEDURE userVolHeatCap_getval + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +END SUBMODULE User \ No newline at end of file From c6d0a9fceda3a27c21b356dfeac366e949798a52 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:43:31 +0900 Subject: [PATCH 093/117] Adding PorousMaterial --- src/submodules/PorousMaterial/CMakeLists.txt | 24 ++++ ...orousMaterial_Class@ConstructorMethods.F90 | 118 ++++++++++++++++++ .../src/PorousMaterial_Class@GetMethods.F90 | 30 +++++ .../src/PorousMaterial_Class@IOMethods.F90 | 96 ++++++++++++++ 4 files changed, 268 insertions(+) create mode 100644 src/submodules/PorousMaterial/CMakeLists.txt create mode 100644 src/submodules/PorousMaterial/src/PorousMaterial_Class@ConstructorMethods.F90 create mode 100644 src/submodules/PorousMaterial/src/PorousMaterial_Class@GetMethods.F90 create mode 100644 src/submodules/PorousMaterial/src/PorousMaterial_Class@IOMethods.F90 diff --git a/src/submodules/PorousMaterial/CMakeLists.txt b/src/submodules/PorousMaterial/CMakeLists.txt new file mode 100644 index 000000000..748c5ca1c --- /dev/null +++ b/src/submodules/PorousMaterial/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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}/PorousMaterial_Class@ConstructorMethods.F90 + ${src_path}/PorousMaterial_Class@IOMethods.F90 + ${src_path}/PorousMaterial_Class@GetMethods.F90 +) diff --git a/src/submodules/PorousMaterial/src/PorousMaterial_Class@ConstructorMethods.F90 b/src/submodules/PorousMaterial/src/PorousMaterial_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..5dee8e851 --- /dev/null +++ b/src/submodules/PorousMaterial/src/PorousMaterial_Class@ConstructorMethods.F90 @@ -0,0 +1,118 @@ +! 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(PorousMaterial_Class) ConstructorMethods +USE MaterialFactory +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! setPorousMaterialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE setPorousMaterialParam +CALL SetAbstractMaterialParam(param=param, & + & prefix=myprefix, name=name) +CALL Set(obj=param, prefix=myprefix, key="stressStrainModel", & + & VALUE=stressStrainModel, dataType="char") +END PROCEDURE setPorousMaterialParam + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "Porous_CheckEssentialParam" +IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/name should be present in param') +END IF +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL obj%stressStrainModel%CheckEssentialParam(param) +END IF +END PROCEDURE Porous_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_Initiate +CHARACTER(*), PARAMETER :: myName = "Porous_Initiate" +TYPE(String) :: prefix0, stressStrainModel +LOGICAL(LGT) :: bool1 +! main + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +IF (PRESENT(prefix)) THEN + prefix0 = prefix +ELSE + prefix0 = obj%GetPrefix() +END IF + +CALL AbstractMaterialInitiate(obj=obj, param=param, prefix=prefix0%chars()) + +! stressStrainModel + +CALL GetValue(obj=param, prefix=prefix0%chars(), key="stressStrainModel", & + & VALUE=stressStrainModel) + +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: The "//prefix0//"/stressStrainModel is "// & + & "already associated, "// & + & CHAR_LF//"nullify it first.") + RETURN +END IF + +bool1 = param%isPresent(key=prefix0//"/stressStrainModel") +IF (bool1) THEN + obj%stressStrainModel => PoroMechanicsModelFactory( & + & stressStrainModel%chars()) + CALL obj%stressStrainModel%Initiate(param) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif +END PROCEDURE Porous_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_Deallocate +CALL AbstractMaterialDeallocate(obj) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + DEALLOCATE (obj%stressStrainModel) + NULLIFY (obj%stressStrainModel) +END IF +END PROCEDURE Porous_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_Final +CALL obj%DEALLOCATE() +END PROCEDURE Porous_Final + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/PorousMaterial/src/PorousMaterial_Class@GetMethods.F90 b/src/submodules/PorousMaterial/src/PorousMaterial_Class@GetMethods.F90 new file mode 100644 index 000000000..485b15ed4 --- /dev/null +++ b/src/submodules/PorousMaterial/src/PorousMaterial_Class@GetMethods.F90 @@ -0,0 +1,30 @@ +! 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(PorousMaterial_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_GetPrefix +ans = myprefix +END PROCEDURE Porous_GetPrefix + +END SUBMODULE GetMethods diff --git a/src/submodules/PorousMaterial/src/PorousMaterial_Class@IOMethods.F90 b/src/submodules/PorousMaterial/src/PorousMaterial_Class@IOMethods.F90 new file mode 100644 index 000000000..c392bfd1b --- /dev/null +++ b/src/submodules/PorousMaterial/src/PorousMaterial_Class@IOMethods.F90 @@ -0,0 +1,96 @@ +! 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(PorousMaterial_Class) IOMethods +USE MaterialFactory +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_Display +! CHARACTER(*), PARAMETER :: myName = "Porous_Display" +CALL AbstractMaterialDisplay(obj=obj, msg=msg, unitNo=unitNo) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL obj%stressStrainModel%Display(msg="stressStrainModel :", & + & unitNo=unitNo) +END IF +END PROCEDURE Porous_Display + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_Import +CHARACTER(*), PARAMETER :: myName = "Porous_Import" +TYPE(String) :: dsetname, strval + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +CALL AbstractMaterialImport(obj=obj, hdf5=hdf5, group=group) + +IF (hdf5%pathExists(TRIM(group)//"/stressStrainModel")) THEN + dsetname = TRIM(group)//"/stressStrainModel/name" + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & 'The dataset ./stressStrainModel/name should be present') + END IF + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + obj%stressStrainModel => PoroMechanicsModelFactory( & + & TRIM(strval%chars())) + dsetname = TRIM(group)//"/stressStrainModel" + CALL obj%stressStrainModel%IMPORT(hdf5=hdf5, & + & group=dsetname%chars()) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif +END PROCEDURE Porous_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Porous_Export +CHARACTER(*), PARAMETER :: myName = "Porous_Export" +TYPE(String) :: dsetname + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Export()') +#endif + +CALL AbstractMaterialExport(obj=obj, hdf5=hdf5, group=group) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + dsetname = TRIM(group)//"/stressStrainModel" + CALL obj%stressStrainModel%export(hdf5=hdf5, group=dsetname%chars()) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif +END PROCEDURE Porous_Export + +END SUBMODULE IOMethods From 593e94aed23c1afbf664a4b1a000bc7e3eb1efae Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:43:41 +0900 Subject: [PATCH 094/117] Adding SolidMaterial --- src/submodules/SolidMaterial/CMakeLists.txt | 24 ++ ...SolidMaterial_Class@ConstructorMethods.F90 | 207 ++++++++++++++++++ .../src/SolidMaterial_Class@GetMethods.F90 | 38 ++++ .../src/SolidMaterial_Class@IOMethods.F90 | 103 +++++++++ 4 files changed, 372 insertions(+) create mode 100644 src/submodules/SolidMaterial/CMakeLists.txt create mode 100644 src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 create mode 100644 src/submodules/SolidMaterial/src/SolidMaterial_Class@GetMethods.F90 create mode 100644 src/submodules/SolidMaterial/src/SolidMaterial_Class@IOMethods.F90 diff --git a/src/submodules/SolidMaterial/CMakeLists.txt b/src/submodules/SolidMaterial/CMakeLists.txt new file mode 100644 index 000000000..bb793ce31 --- /dev/null +++ b/src/submodules/SolidMaterial/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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}/SolidMaterial_Class@ConstructorMethods.F90 + ${src_path}/SolidMaterial_Class@IOMethods.F90 + ${src_path}/SolidMaterial_Class@GetMethods.F90 +) diff --git a/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 b/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..068f26c3c --- /dev/null +++ b/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 @@ -0,0 +1,207 @@ +! 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(SolidMaterial_Class) ConstructorMethods +USE BaseMethod, ONLY: ToString +USE MaterialFactory +USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! setSolidMaterialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE SetSolidMaterialParam +CALL SetAbstractMaterialParam(param=param, prefix=myprefix, name=name) +CALL Set(obj=param, prefix=myprefix, key="stressStrainModel", & + & VALUE=stressStrainModel, dataType="char") +END PROCEDURE SetSolidMaterialParam + +!---------------------------------------------------------------------------- +! CheckEssentialParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "solid_CheckEssentialParam()" +IF (.NOT. param%isPresent(key=myprefix//"/name")) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & myprefix//'/name should be present in param') +END IF +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL obj%stressStrainModel%CheckEssentialParam(param) +END IF +END PROCEDURE solid_CheckEssentialParam + +!---------------------------------------------------------------------------- +! Initiate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_Initiate +CHARACTER(*), PARAMETER :: myName = "solid_Initiate()" +TYPE(String) :: prefix0, stressStrainModel +LOGICAL(LGT) :: bool1 +! main + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Initiate()') +#endif + +IF (PRESENT(prefix)) THEN + prefix0 = prefix +ELSE + prefix0 = obj%GetPrefix() +END IF + +CALL AbstractMaterialInitiate(obj=obj, param=param, prefix=prefix0%chars()) + +! stressStrainModel + +CALL GetValue(obj=param, prefix=prefix0%chars(), key="stressStrainModel", & + & VALUE=stressStrainModel) + +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & "[CONFIG ERROR] :: The "//prefix0//"/stressStrainModel is "// & + & "already associated, "// & + & CHAR_LF//"nullify it first.") + RETURN +END IF + +bool1 = param%isPresent(key=prefix0//"/stressStrainModel") +IF (bool1) THEN + obj%stressStrainModel => SolidMechanicsModelFactory( & + & stressStrainModel%chars()) + CALL obj%stressStrainModel%Initiate(param) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Initiate()') +#endif +END PROCEDURE solid_Initiate + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_Deallocate +CALL AbstractMaterialDeallocate(obj) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + DEALLOCATE (obj%stressStrainModel) + NULLIFY (obj%stressStrainModel) +END IF +END PROCEDURE solid_Deallocate + +!---------------------------------------------------------------------------- +! Final +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_Final +CALL obj%DEALLOCATE() +END PROCEDURE solid_Final + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Deallocate_Vector +INTEGER(I4B) :: ii +IF (ALLOCATED(obj)) THEN + DO ii = 1, SIZE(obj) + CALL obj(ii)%DEALLOCATE() + END DO + DEALLOCATE (obj) +END IF +END PROCEDURE Deallocate_Vector + +!---------------------------------------------------------------------------- +! Deallocate +!---------------------------------------------------------------------------- + +MODULE PROCEDURE Deallocate_Ptr_Vector +INTEGER(I4B) :: ii +IF (ALLOCATED(obj)) THEN + DO ii = 1, SIZE(obj) + IF (ASSOCIATED(obj(ii)%ptr)) THEN + CALL obj(ii)%ptr%DEALLOCATE() + obj(ii)%ptr => NULL() + END IF + END DO + DEALLOCATE (obj) +END IF +END PROCEDURE Deallocate_Ptr_Vector + +!---------------------------------------------------------------------------- +! solid_AddSolidMaterial +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_AddSolidMaterial +CHARACTER(*), PARAMETER :: myName = "solid_AddSolidMaterial" + +IF (materialNo .GT. tMaterials) THEN + + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & + & '] is greater than total number of solidMaterials [='// & + & TOSTRING(tMaterials)//']!') + +END IF + +IF (PRESENT(region) .AND. PRESENT(solidMaterialToMesh)) THEN + + IF (materialNo .GT. SIZE(solidMaterialToMesh)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & + & '] is greater than the size of solidMaterialToMesh [='// & + & TOSTRING(SIZE(solidMaterialToMesh))//']!') + END IF + solidMaterialToMesh(materialNo) = region + +END IF + +IF (PRESENT(param)) THEN + + IF (materialNo .GT. SIZE(obj)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & + & '] is greater than the size of solidMaterial[='// & + & TOSTRING(SIZE(obj))//']!') + END IF + + IF (ASSOCIATED(obj(materialNo)%ptr)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[POINTER ERROR] :: solidMaterial('//TOSTRING(materialNo)// & + & ')%ptr is already associated.') + END IF + + IF (.NOT. PRESENT(materialName)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[ARG MISSING] :: materialName should be present.') + END IF + + obj(materialNo)%ptr => & + & SolidMaterialFactory(TRIM(materialName)) + !! INFO: Solid material factory is defined in MaterialFactory. + + CALL obj(materialNo)%ptr%initiate(param) + +END IF + +END PROCEDURE solid_AddSolidMaterial + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/SolidMaterial/src/SolidMaterial_Class@GetMethods.F90 b/src/submodules/SolidMaterial/src/SolidMaterial_Class@GetMethods.F90 new file mode 100644 index 000000000..5d4074a1e --- /dev/null +++ b/src/submodules/SolidMaterial/src/SolidMaterial_Class@GetMethods.F90 @@ -0,0 +1,38 @@ +! 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(SolidMaterial_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_GetStressStrainModelPointer +ans => obj%stressStrainModel +END PROCEDURE solid_GetStressStrainModelPointer + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_GetPrefix +ans = myprefix +END PROCEDURE solid_GetPrefix + +END SUBMODULE GetMethods diff --git a/src/submodules/SolidMaterial/src/SolidMaterial_Class@IOMethods.F90 b/src/submodules/SolidMaterial/src/SolidMaterial_Class@IOMethods.F90 new file mode 100644 index 000000000..ca5730127 --- /dev/null +++ b/src/submodules/SolidMaterial/src/SolidMaterial_Class@IOMethods.F90 @@ -0,0 +1,103 @@ +! 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(SolidMaterial_Class) IOMethods +USE MaterialFactory +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_Display +! CHARACTER(*), PARAMETER :: myName = "solid_Display" +! main +CALL AbstractMaterialDisplay(obj=obj, msg=msg, unitNo=unitNo) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + CALL obj%stressStrainModel%Display(msg="# stressStrainModel :", & + & unitNo=unitNo) +END IF +END PROCEDURE solid_Display + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_Import +CHARACTER(*), PARAMETER :: myName = "solid_Import" +TYPE(String) :: dsetname, strval + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] Import()') +#endif + +CALL AbstractMaterialImport(obj=obj, hdf5=hdf5, group=group) + +! stressStrainModel +IF (hdf5%pathExists(TRIM(group)//"/stressStrainModel")) THEN + dsetname = TRIM(group)//"/stressStrainModel/name" + + IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[CONIFG ERROR] :: dataset ./stressStrainModel/name '// & + & 'should be present.') + RETURN + END IF + + CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) + obj%stressStrainModel => SolidMechanicsModelFactory( & + & TRIM(strval%chars())) + dsetname = TRIM(group)//"/stressStrainModel" + CALL obj%stressStrainModel%IMPORT(hdf5=hdf5, & + & group=dsetname%chars()) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Import()') +#endif +END PROCEDURE solid_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_Export +CHARACTER(*), PARAMETER :: myName = "solid_Export" +TYPE(String) :: dsetname + +#ifdef DEBUG_VER +CALL e%raiseInformation(modName//"::"//myName//" - "// & + & "[START] Export()") +#endif + +CALL AbstractMaterialExport(obj=obj, hdf5=hdf5, group=group) +IF (ASSOCIATED(obj%stressStrainModel)) THEN + dsetname = TRIM(group)//"/stressStrainModel" + CALL obj%stressStrainModel%export(hdf5=hdf5, group=dsetname%chars()) +END IF + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] Export()') +#endif + +END PROCEDURE solid_Export + +END SUBMODULE IOMethods From eb7c1677734682566d5d2024f878f3c3fedf86ad Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 00:43:51 +0900 Subject: [PATCH 095/117] Adding cmake --- src/submodules/CMakeLists.txt | 214 +++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 94 deletions(-) diff --git a/src/submodules/CMakeLists.txt b/src/submodules/CMakeLists.txt index 7855c6d1a..b5621f1cf 100644 --- a/src/submodules/CMakeLists.txt +++ b/src/submodules/CMakeLists.txt @@ -1,260 +1,286 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# You should have received a copy of the GNU General Public License along with +# this program. If not, see # # ExceptionHandler -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ExceptionHandler/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ExceptionHandler/CMakeLists.txt) # AbstractFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFile/CMakeLists.txt) # FortranFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FortranFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FortranFile/CMakeLists.txt) # TxtFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/TxtFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/TxtFile/CMakeLists.txt) # CSVFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/CSVFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/CSVFile/CMakeLists.txt) # InputFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/InputFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/InputFile/CMakeLists.txt) # HDF5File -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/HDF5File/CMakeLists.txt) # XMLFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/XMLFile/CMakeLists.txt) # VTKFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VTKFile/CMakeLists.txt) # Toml -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Toml/CMakeLists.txt) # Element -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Element/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Element/CMakeLists.txt) # FacetElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FacetElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FacetElement/CMakeLists.txt) # MSHFile -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MSHFile/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MSHFile/CMakeLists.txt) # Mesh -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Mesh/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Mesh/CMakeLists.txt) # Domain -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Domain/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Domain/CMakeLists.txt) # DomainConnectivity -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/DomainConnectivity/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/DomainConnectivity/CMakeLists.txt) # MeshSelection -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MeshSelection/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MeshSelection/CMakeLists.txt) # Vector -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Vector/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Vector/CMakeLists.txt) # AbstractField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractField/CMakeLists.txt) # AbstractNodeField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractNodeField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractNodeField/CMakeLists.txt) # AbstractMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMeshField/CMakeLists.txt) # ScalarMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ScalarMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ScalarMeshField/CMakeLists.txt) # STScalarMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STScalarMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STScalarMeshField/CMakeLists.txt) # VectorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VectorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VectorMeshField/CMakeLists.txt) # STVectorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STVectorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STVectorMeshField/CMakeLists.txt) # TensorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/TensorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/TensorMeshField/CMakeLists.txt) # STTensorMeshField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STTensorMeshField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STTensorMeshField/CMakeLists.txt) # ScalarField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ScalarField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ScalarField/CMakeLists.txt) # ScalarFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ScalarFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ScalarFieldLis/CMakeLists.txt) # STScalarField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STScalarField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STScalarField/CMakeLists.txt) # STScalarFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STScalarFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STScalarFieldLis/CMakeLists.txt) # VectorField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VectorField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VectorField/CMakeLists.txt) # VectorFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VectorFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VectorFieldLis/CMakeLists.txt) # STVectorField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STVectorField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STVectorField/CMakeLists.txt) # STVectorFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/STVectorFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/STVectorFieldLis/CMakeLists.txt) # BlockNodeField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockNodeField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockNodeField/CMakeLists.txt) # BlockNodeFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockNodeFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockNodeFieldLis/CMakeLists.txt) # AbstractMatrixField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractMatrixField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMatrixField/CMakeLists.txt) # MatrixField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MatrixField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MatrixField/CMakeLists.txt) # MatrixFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MatrixFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MatrixFieldLis/CMakeLists.txt) # BlockMatrixField -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixField/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixField/CMakeLists.txt) # BlockMatrixFieldLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixFieldLis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/BlockMatrixFieldLis/CMakeLists.txt) # FieldFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FieldFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FieldFactory/CMakeLists.txt) # AbstractBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractBC/CMakeLists.txt) # DirichletBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/DirichletBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/DirichletBC/CMakeLists.txt) # NeumannBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/NeumannBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/NeumannBC/CMakeLists.txt) # NitscheBC -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/NitscheBC/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/NitscheBC/CMakeLists.txt) # AbstractLinSolver -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractLinSolver/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractLinSolver/CMakeLists.txt) # LinSolver -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/LinSolver/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/LinSolver/CMakeLists.txt) -# LinSolverLis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/LinSolverLis/CMakeLists.txt) +# LinSolverLis +include(${CMAKE_CURRENT_LIST_DIR}/LinSolverLis/CMakeLists.txt) # LinSolverFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/LinSolverFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/LinSolverFactory/CMakeLists.txt) # AbstractFunction -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFunction/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFunction/CMakeLists.txt) # AbstractBasis -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractBasis/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractBasis/CMakeLists.txt) # Monomial1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Monomial1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Monomial1D/CMakeLists.txt) # Monomial2D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Monomial2D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Monomial2D/CMakeLists.txt) # Monomial3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Monomial3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Monomial3D/CMakeLists.txt) # MonomialND -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MonomialND/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MonomialND/CMakeLists.txt) # AbstractPolynomial -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractPolynomial/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractPolynomial/CMakeLists.txt) # Polynomial1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Polynomial1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Polynomial1D/CMakeLists.txt) # Polynomial2D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Polynomial2D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Polynomial2D/CMakeLists.txt) # Polynomial3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Polynomial3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Polynomial3D/CMakeLists.txt) # PolynomialND -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PolynomialND/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/PolynomialND/CMakeLists.txt) # Lagrange1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange1D/CMakeLists.txt) # Lagrange2D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange2D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange2D/CMakeLists.txt) # Lagrange3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange3D/CMakeLists.txt) # Lagrange3D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Lagrange3D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Lagrange3D/CMakeLists.txt) # AbstractOrthopol1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractOrthopol1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractOrthopol1D/CMakeLists.txt) # Jacobi1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Jacobi1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Jacobi1D/CMakeLists.txt) # Ultraspherical1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Ultraspherical1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Ultraspherical1D/CMakeLists.txt) # Legendre1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Legendre1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Legendre1D/CMakeLists.txt) # ChebyshevFirst1D -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/ChebyshevFirst1D/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/ChebyshevFirst1D/CMakeLists.txt) # PolynomialFactory -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PolynomialFactory/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/PolynomialFactory/CMakeLists.txt) # Tree3R -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Tree3R/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/Tree3R/CMakeLists.txt) # UserFunction -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/UserFunction/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/UserFunction/CMakeLists.txt) # RefElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/RefElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/RefElement/CMakeLists.txt) # AbstractFE -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractFE/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractFE/CMakeLists.txt) # FiniteElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FiniteElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/FiniteElement/CMakeLists.txt) # MixedFiniteElement -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/MixedFiniteElement/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/MixedFiniteElement/CMakeLists.txt) # AbstractPlot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/AbstractPlot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/AbstractPlot/CMakeLists.txt) # VTKPlot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/VTKPlot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/VTKPlot/CMakeLists.txt) # PLPlot -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) +# AbstractSolidMechanicsModel +include(${CMAKE_CURRENT_LIST_DIR}/AbstractSolidMechanicsModel/CMakeLists.txt) + +# LinearElasticModel +include(${CMAKE_CURRENT_LIST_DIR}/LinearElasticModel/CMakeLists.txt) + +# LinearPoroElasticModel +include(${CMAKE_CURRENT_LIST_DIR}/LinearPoroElasticModel/CMakeLists.txt) + +# NewtonianFluidModel +include(${CMAKE_CURRENT_LIST_DIR}/NewtonianFluidModel/CMakeLists.txt) + +# MaterialFactory +include(${CMAKE_CURRENT_LIST_DIR}/MaterialFactory/CMakeLists.txt) + +# AbstractMaterial +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMaterial/CMakeLists.txt) + +# SolidMaterial +include(${CMAKE_CURRENT_LIST_DIR}/SolidMaterial/CMakeLists.txt) + +# fluidMaterial +include(${CMAKE_CURRENT_LIST_DIR}/FluidMaterial/CMakeLists.txt) + +# porousMaterial +include(${CMAKE_CURRENT_LIST_DIR}/PorousMaterial/CMakeLists.txt) From 87cedc3bfcfd445e95b74e137ac577b40fa92b51 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 18:36:48 +0900 Subject: [PATCH 096/117] Update easifemClasses.F90 Removing easifemMaterials from easifemClasses module --- src/modules/easifemClasses/src/easifemClasses.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/easifemClasses/src/easifemClasses.F90 b/src/modules/easifemClasses/src/easifemClasses.F90 index 3d84e8327..455196306 100644 --- a/src/modules/easifemClasses/src/easifemClasses.F90 +++ b/src/modules/easifemClasses/src/easifemClasses.F90 @@ -69,5 +69,4 @@ MODULE easifemClasses USE TomlUtility -USE easifemMaterials END MODULE easifemClasses From 406537028cfb47469956004f926362b22eb46138 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 18:37:31 +0900 Subject: [PATCH 097/117] Update in Materials Working towards issue #212 --- .../src/AbstractMaterial_Class.F90 | 28 ++- .../src/AbstractMaterialModel_Class.F90 | 48 +++- .../SolidMaterial/src/SolidMaterial_Class.F90 | 125 +++++----- .../src/AbstractMaterial_Class@IOMethods.F90 | 221 ++++++++++-------- src/submodules/SolidMaterial/CMakeLists.txt | 38 +-- ...SolidMaterial_Class@ConstructorMethods.F90 | 80 +------ .../src/SolidMaterial_Class@SetMethods.F90 | 82 +++++++ 7 files changed, 374 insertions(+), 248 deletions(-) create mode 100644 src/submodules/SolidMaterial/src/SolidMaterial_Class@SetMethods.F90 diff --git a/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 b/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 index 2238e45c9..7b52cda19 100644 --- a/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 +++ b/src/modules/AbstractMaterial/src/AbstractMaterial_Class.F90 @@ -29,6 +29,7 @@ MODULE AbstractMaterial_Class USE FPL, ONLY: ParameterList_ USE TxtFile_Class USE tomlf, ONLY: toml_table +USE tomlf, ONLY: toml_array USE Fhash, ONLY: FhashTable_ => fhash_tbl_t IMPLICIT NONE PRIVATE @@ -104,10 +105,10 @@ MODULE AbstractMaterial_Class PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => am_Import PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml1 => & & am_ImportFromToml1 - PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml2 => & - & am_ImportFromToml2 - GENERIC, PUBLIC :: ImportFromTom => ImportFromToml1, & - & ImportFromToml2 + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml2 => am_ImportFromToml2 + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml3 => am_ImportFromToml3 + GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, ImportFromToml2, & + & ImportFromToml3 ! GET: ! @GetMethods @@ -336,19 +337,34 @@ END SUBROUTINE am_ImportFromToml1 ! ImportFromToml@IOMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE AbstractMaterialImportFromToml + MODULE SUBROUTINE am_ImportFromToml2(obj, array) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + TYPE(toml_array), POINTER, INTENT(INOUT) :: array + END SUBROUTINE am_ImportFromToml2 +END INTERFACE AbstractMaterialImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + !> author: Vikas Sharma, Ph. D. ! date: 2023-11-08 ! summary: Initiate kernel from the toml file INTERFACE AbstractMaterialImportFromToml - MODULE SUBROUTINE am_ImportFromToml2(obj, tomlName, afile, filename, & + MODULE SUBROUTINE am_ImportFromToml3(obj, tomlName, afile, filename, & & printToml) CLASS(AbstractMaterial_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: tomlName TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile CHARACTER(*), OPTIONAL, INTENT(IN) :: filename LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml - END SUBROUTINE am_ImportFromToml2 + END SUBROUTINE am_ImportFromToml3 END INTERFACE AbstractMaterialImportFromToml END MODULE AbstractMaterial_Class diff --git a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 index fc6694c6b..f27d64ff8 100644 --- a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 +++ b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 @@ -46,17 +46,29 @@ MODULE AbstractMaterialModel_Class TYPE(String) :: name CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE(amb_CheckEssentialParam), DEFERRED, PUBLIC, PASS(obj) :: & & CheckEssentialParam PROCEDURE(amb_Initiate), DEFERRED, PUBLIC, PASS(obj) :: Initiate PROCEDURE(amb_Deallocate), DEFERRED, PUBLIC, PASS(obj) :: & & DEALLOCATE + PROCEDURE, PUBLIC, PASS(obj) :: isInitiated => amb_isInitiated + + ! IO: + ! @IOMethods PROCEDURE(amb_Import), DEFERRED, PUBLIC, PASS(obj) :: IMPORT PROCEDURE(amb_Export), DEFERRED, PUBLIC, PASS(obj) :: Export PROCEDURE(amb_Display), DEFERRED, PUBLIC, PASS(obj) :: Display + + ! GET: + ! @GetMethods PROCEDURE(amb_GetPrefix), DEFERRED, PUBLIC, PASS(obj) :: GetPrefix - PROCEDURE, PUBLIC, PASS(obj) :: isInitiated => amb_isInitiated PROCEDURE, PUBLIC, PASS(obj) :: GetName => amb_GetName + + ! SET: + ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: SetIsInitiated => amb_SetIsInitiated PROCEDURE, PUBLIC, PASS(obj) :: SetName => amb_SetName END TYPE AbstractMaterialModel_ @@ -208,4 +220,38 @@ SUBROUTINE amb_SetName(obj, VALUE) obj%name = VALUE END SUBROUTINE amb_SetName +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE AbstractMaterialImportFromToml + MODULE SUBROUTINE am_ImportFromToml1(obj, table) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE am_ImportFromToml1 +END INTERFACE AbstractMaterialImportFromToml + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE AbstractMaterialImportFromToml + MODULE SUBROUTINE am_ImportFromToml3(obj, tomlName, afile, filename, & + & printToml) + CLASS(AbstractMaterial_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE am_ImportFromToml3 +END INTERFACE AbstractMaterialImportFromToml + END MODULE AbstractMaterialModel_Class diff --git a/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 b/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 index bdf7df8fd..c0e50138b 100644 --- a/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 +++ b/src/modules/SolidMaterial/src/SolidMaterial_Class.F90 @@ -65,19 +65,32 @@ MODULE SolidMaterial_Class !! Pointer to stress strain material behavior of solids CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & solid_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate => solid_Initiate PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => solid_Deallocate FINAL :: solid_Final + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => solid_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => solid_Export PROCEDURE, PUBLIC, PASS(obj) :: Display => solid_Display + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetStressStrainModelPointer => & & solid_GetStressStrainModelPointer PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => solid_GetPrefix END TYPE SolidMaterial_ +!---------------------------------------------------------------------------- +! TypeSolidMaterial +!---------------------------------------------------------------------------- + TYPE(SolidMaterial_), PARAMETER :: TypeSolidMaterial = SolidMaterial_() !---------------------------------------------------------------------------- @@ -88,34 +101,6 @@ MODULE SolidMaterial_Class CLASS(SolidMaterial_), POINTER :: ptr => NULL() END TYPE SolidMaterialPointer_ -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-09 -! summary: Deallocate the vector - -INTERFACE DEALLOCATE - MODULE SUBROUTINE Deallocate_Vector(obj) - TYPE(SolidMaterial_), ALLOCATABLE :: obj(:) - END SUBROUTINE Deallocate_Vector -END INTERFACE DEALLOCATE - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-09 -! summary: Deallocate the vector of pointer - -INTERFACE DEALLOCATE - MODULE SUBROUTINE Deallocate_Ptr_Vector(obj) - TYPE(SolidMaterialPointer_), ALLOCATABLE :: obj(:) - END SUBROUTINE Deallocate_Ptr_Vector -END INTERFACE DEALLOCATE - !---------------------------------------------------------------------------- ! SetSolidMaterialParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -158,7 +143,6 @@ END SUBROUTINE SetSolidMaterialParam ! It Checks the existance of ! ! - `SolidMaterial/name` -! - `SolidMaterial/massDensity` ! - `SolidMaterial/stresStrainModel` INTERFACE @@ -181,7 +165,6 @@ END SUBROUTINE solid_CheckEssentialParam ! It reads the options from `param`, and sets the options of `SolidMaterial` ! !- `SolidMaterial/name` -!- `SolidMaterial/massDensity` !- `SolidMaterial/stresStrainModel` ! ! This routine calls the [[MaterialFactory:SolidMechanicsModelFactory]] to @@ -201,6 +184,33 @@ MODULE SUBROUTINE solid_Initiate(obj, param, prefix) END SUBROUTINE solid_Initiate END INTERFACE +!---------------------------------------------------------------------------- +! AddSolidMaterial@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-11 +! summary: Add a solid material to the vector of SolidMaterialPointer_ + +INTERFACE AddSolidMaterial + MODULE SUBROUTINE solid_AddSolidMaterial( & + & obj, & + & tMaterials, & + & materialNo, & + & materialName, & + & solidMaterialToMesh, & + & param, & + & region) + TYPE(SolidMaterialPointer_), INTENT(INOUT) :: obj(:) + INTEGER(I4B), INTENT(IN) :: tMaterials + INTEGER(I4B), INTENT(IN) :: materialNo + CHARACTER(*), OPTIONAL, INTENT(IN) :: materialName + TYPE(ParameterList_), OPTIONAL, INTENT(IN) :: param + TYPE(MeshSelection_), OPTIONAL, INTENT(IN) :: region + TYPE(MeshSelection_), OPTIONAL, INTENT(INOUT) :: solidMaterialToMesh(:) + END SUBROUTINE solid_AddSolidMaterial +END INTERFACE AddSolidMaterial + !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -225,6 +235,34 @@ MODULE SUBROUTINE solid_Deallocate(obj) END SUBROUTINE solid_Deallocate END INTERFACE +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Deallocate the vector + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Vector(obj) + TYPE(SolidMaterial_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Vector +END INTERFACE DEALLOCATE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-09-09 +! summary: Deallocate the vector of pointer + +INTERFACE DEALLOCATE + MODULE SUBROUTINE Deallocate_Ptr_Vector(obj) + TYPE(SolidMaterialPointer_), ALLOCATABLE :: obj(:) + END SUBROUTINE Deallocate_Ptr_Vector +END INTERFACE DEALLOCATE + !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -307,33 +345,6 @@ MODULE FUNCTION solid_GetStressStrainModelPointer(obj) RESULT(ans) END FUNCTION solid_GetStressStrainModelPointer END INTERFACE -!---------------------------------------------------------------------------- -! AddSolidMaterial@SetMethod -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-09-11 -! summary: Add a solid material to the vector of SolidMaterialPointer_ - -INTERFACE AddSolidMaterial - MODULE SUBROUTINE solid_AddSolidMaterial( & - & obj, & - & tMaterials, & - & materialNo, & - & materialName, & - & solidMaterialToMesh, & - & param, & - & region) - TYPE(SolidMaterialPointer_), INTENT(INOUT) :: obj(:) - INTEGER(I4B), INTENT(IN) :: tMaterials - INTEGER(I4B), INTENT(IN) :: materialNo - CHARACTER(*), OPTIONAL, INTENT(IN) :: materialName - TYPE(ParameterList_), OPTIONAL, INTENT(IN) :: param - TYPE(MeshSelection_), OPTIONAL, INTENT(IN) :: region - TYPE(MeshSelection_), OPTIONAL, INTENT(INOUT) :: solidMaterialToMesh(:) - END SUBROUTINE solid_AddSolidMaterial -END INTERFACE AddSolidMaterial - !---------------------------------------------------------------------------- ! GetPrefix@GetMethods !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 index 8d4bb5bf1..6414fc0e0 100644 --- a/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 +++ b/src/submodules/AbstractMaterial/src/AbstractMaterial_Class@IOMethods.F90 @@ -23,7 +23,6 @@ & toml_serialize, & & toml_get => get_value, & & toml_len => len, & - & toml_array, & & toml_stat IMPLICIT NONE CONTAINS @@ -42,8 +41,10 @@ CALL Display(msg, unitNo=unitNo) CALL Display(obj%isInit, "isInitiated : ", unitNo=unitNo) IF (.NOT. obj%isInit) RETURN + CALL Display("name : "//obj%name%chars(), unitNo=unitNo) CALL Display(obj%tProperties, "total Properties: ", unitNo=unitNo) +CALL BlankLines(unitNo=unitNo, nol=1) iter = fhash_iter_t(obj%tbl) @@ -57,6 +58,8 @@ END DO +CALL BlankLines(unitNo=unitNo, nol=1) + matalloc = ALLOCATED(obj%matProps) CALL Display(matalloc, "matProps ALLOCATED: ", unitNo=unitNo) @@ -67,8 +70,10 @@ DO ii = 1, tsize isOK = ASSOCIATED(obj%matProps(ii)%ptr) IF (isOK) THEN + CALL BlankLines(unitNo=unitNo, nol=1) CALL obj%matProps(ii)%ptr%Display("material Properties("// & & tostring(ii)//"):", unitNo=unitNo) + CALL EqualLine(unitNo=unitNo) END IF END DO @@ -176,21 +181,59 @@ MODULE PROCEDURE am_ImportFromToml1 CHARACTER(*), PARAMETER :: myName = "am_ImportFromToml1()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR]') +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: isOK +TYPE(ParameterList_) :: param +CHARACTER(:), ALLOCATABLE :: name +CLASS(UserFunction_), POINTER :: afunc + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif + +CALL param%Initiate() +CALL SetAbstractMaterialParam(param=param, prefix=obj%GetPrefix(), & + & name=obj%GetPrefix()) +CALL obj%Initiate(param=param) +CALL param%DEALLOCATE() + +! get name of the property from the node (table) +CALL toml_get(table, "name", name, origin=origin, stat=stat) + +isOK = ALLOCATED(name) .AND. (stat .EQ. toml_stat%success) +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: cannot find/read "name" in the config file.') + RETURN +END IF + +CALL obj%AddMaterial(name=name) +afunc => NULL() +afunc => obj%GetMaterialPointer(name=name) +isOK = ASSOCIATED(afunc) + +IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: Error while adding a material to list.') + RETURN +END IF + +CALL afunc%ImportFromToml(table=table) +afunc => NULL() +name = "" + END PROCEDURE am_ImportFromToml1 !---------------------------------------------------------------------------- -! ImportFromToml +! ImportFromToml !---------------------------------------------------------------------------- MODULE PROCEDURE am_ImportFromToml2 CHARACTER(*), PARAMETER :: myName = "am_ImportFromToml2()" -TYPE(toml_table), ALLOCATABLE :: table TYPE(toml_table), POINTER :: node -TYPE(toml_array), POINTER :: array INTEGER(I4B) :: origin, stat, tsize, ii -LOGICAL(LGT) :: isTable, isOK, isArray +LOGICAL(LGT) :: isOK TYPE(ParameterList_) :: param CHARACTER(:), ALLOCATABLE :: name CLASS(UserFunction_), POINTER :: afunc @@ -200,40 +243,35 @@ & '[START] ImportFromToml()') #endif -! Get the entire file in table -IF (PRESENT(afile)) THEN - CALL GetValue(table=table, afile=afile) -ELSEIF (PRESENT(filename)) THEN - CALL GetValue(table=table, filename=filename) -ELSE - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[ARG ERROR] :: either filename or afile should be present!') - RETURN -END IF +tsize = toml_len(array) -! get tomlName from the table -node => NULL() -CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & - & stat=stat) +CALL param%Initiate() +CALL SetAbstractMaterialParam(param=param, prefix=obj%GetPrefix(), & + & name=obj%GetPrefix()) +CALL obj%Initiate(param=param) +CALL param%DEALLOCATE() -! The node can be a table or array of table; first thing first. -isTable = ASSOCIATED(node) .AND. (stat .EQ. toml_stat%success) +DO ii = 1, tsize + node => NULL() + CALL toml_get(array, ii, node) + isOK = ASSOCIATED(node) -IF (isTable) THEN - CALL param%Initiate() - CALL SetAbstractMaterialParam(param=param, prefix=obj%GetPrefix(), & - & name=obj%GetPrefix()) - CALL obj%Initiate(param=param) - CALL param%DEALLOCATE() + IF (.NOT. isOK) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: In toml file '//tostring(ii)// & + & 'th material cannot be read.') + RETURN + END IF ! get name of the property from the node (table) + name = "" CALL toml_get(node, "name", name, origin=origin, stat=stat) isOK = ALLOCATED(name) .AND. (stat .EQ. toml_stat%success) IF (.NOT. isOK) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: cannot find/read "name" from '//tomlName// & - & ' in the config file.') + & '[INTERNAL ERROR] :: cannot find/read "name" from material number ' & + & //tostring(ii)//' in the config file.') RETURN END IF @@ -244,95 +282,88 @@ IF (.NOT. isOK) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Error while adding a material to list.') + & '[INTERNAL ERROR] :: Error while adding material name='// & + & name//' to list. This is '//tostring(ii)//'th material.') RETURN END IF CALL afunc%ImportFromToml(table=node) - afunc => NULL() +END DO + +afunc => NULL() +node => NULL() #ifdef DEBUG_VER - IF (PRESENT(printToml)) THEN - CALL Display(toml_serialize(node), "toml config = "//CHAR_LF, & - & unitNo=stdout) - END IF +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] ImportFromToml()') #endif - node => NULL() +END PROCEDURE am_ImportFromToml2 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE am_ImportFromToml3 +CHARACTER(*), PARAMETER :: myName = "am_ImportFromToml3()" +TYPE(toml_table), ALLOCATABLE :: table +TYPE(toml_table), POINTER :: node +TYPE(toml_array), POINTER :: array +INTEGER(I4B) :: origin, stat +LOGICAL(LGT) :: isTable, isArray +TYPE(ParameterList_) :: param + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] ImportFromToml()') +#endif +! Get the entire file in table +IF (PRESENT(afile)) THEN + CALL GetValue(table=table, afile=afile) +ELSEIF (PRESENT(filename)) THEN + CALL GetValue(table=table, filename=filename) +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[ARG ERROR] :: either filename or afile should be present!') + RETURN END IF -!! Try for an array of material tables -IF (.NOT. isTable) THEN - array => NULL() +! get tomlName from the table +node => NULL() +array => NULL() +CALL toml_get(table, tomlName, node, origin=origin, requested=.FALSE., & + & stat=stat) + +! The node can be a table or array of table; first thing first. +isTable = ASSOCIATED(node) .AND. (stat .EQ. toml_stat%success) + +IF (isTable) THEN + CALL obj%ImportFromToml(table=node) + +ELSE + ! Try for an array of material tables CALL toml_get(table, tomlName, array, origin=origin, requested=.FALSE., & & stat=stat) isArray = ASSOCIATED(array) .AND. (stat .EQ. toml_stat%success) IF (.NOT. isArray) THEN CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Cannot read/found the array '//tomlName// & - & 'from the toml config.') + & '[INTERNAL ERROR] :: Cannot found the array from the toml config.') RETURN END IF - tsize = toml_len(array) - - CALL param%Initiate() - CALL SetAbstractMaterialParam(param=param, prefix=obj%GetPrefix(), & - & name=obj%GetPrefix()) - CALL obj%Initiate(param=param) - CALL param%DEALLOCATE() - - DO ii = 1, tsize - node => NULL() - CALL toml_get(array, ii, node) - isOK = ASSOCIATED(node) - - IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: In toml file '//tostring(ii)// & - & 'th material cannot be read.') - RETURN - END IF - - ! get name of the property from the node (table) - name = "" - CALL toml_get(node, "name", name, origin=origin, stat=stat) - - isOK = ALLOCATED(name) .AND. (stat .EQ. toml_stat%success) - IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: cannot find/read "name" from '//tomlName// & - & 'material number '//tostring(ii)//' in the config file.') - RETURN - END IF - - CALL obj%AddMaterial(name=name) - afunc => NULL() - afunc => obj%GetMaterialPointer(name=name) - isOK = ASSOCIATED(afunc) - - IF (.NOT. isOK) THEN - CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[INTERNAL ERROR] :: Error while adding material nane='// & - & name//' to list. This is '//tostring(ii)//'th material.') - RETURN - END IF - - CALL afunc%ImportFromToml(table=node) - END DO - - afunc => NULL() - node => NULL() - array => NULL() + CALL obj%ImportFromToml(array=array) END IF +node => NULL() +array => NULL() + #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & - & '[END] ImportParamFromToml()') + & '[END] ImportFromToml()') #endif -END PROCEDURE am_ImportFromToml2 +END PROCEDURE am_ImportFromToml3 END SUBMODULE IOMethods diff --git a/src/submodules/SolidMaterial/CMakeLists.txt b/src/submodules/SolidMaterial/CMakeLists.txt index bb793ce31..e6c693de1 100644 --- a/src/submodules/SolidMaterial/CMakeLists.txt +++ b/src/submodules/SolidMaterial/CMakeLists.txt @@ -1,24 +1,24 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# 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}/SolidMaterial_Class@ConstructorMethods.F90 - ${src_path}/SolidMaterial_Class@IOMethods.F90 - ${src_path}/SolidMaterial_Class@GetMethods.F90 -) +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} + PRIVATE ${src_path}/SolidMaterial_Class@ConstructorMethods.F90 + ${src_path}/SolidMaterial_Class@IOMethods.F90 + ${src_path}/SolidMaterial_Class@GetMethods.F90 + ${src_path}/SolidMaterial_Class@SetMethods.F90) diff --git a/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 b/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 index 068f26c3c..6feb317c9 100644 --- a/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 +++ b/src/submodules/SolidMaterial/src/SolidMaterial_Class@ConstructorMethods.F90 @@ -41,9 +41,6 @@ CALL e%RaiseError(modName//'::'//myName//" - "// & & myprefix//'/name should be present in param') END IF -IF (ASSOCIATED(obj%stressStrainModel)) THEN - CALL obj%stressStrainModel%CheckEssentialParam(param) -END IF END PROCEDURE solid_CheckEssentialParam !---------------------------------------------------------------------------- @@ -67,13 +64,6 @@ prefix0 = obj%GetPrefix() END IF -CALL AbstractMaterialInitiate(obj=obj, param=param, prefix=prefix0%chars()) - -! stressStrainModel - -CALL GetValue(obj=param, prefix=prefix0%chars(), key="stressStrainModel", & - & VALUE=stressStrainModel) - IF (ASSOCIATED(obj%stressStrainModel)) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & & "[CONFIG ERROR] :: The "//prefix0//"/stressStrainModel is "// & @@ -82,10 +72,18 @@ RETURN END IF +CALL AbstractMaterialInitiate(obj=obj, param=param, prefix=prefix0%chars()) + bool1 = param%isPresent(key=prefix0//"/stressStrainModel") IF (bool1) THEN + ! stressStrainModel + CALL GetValue(obj=param, prefix=prefix0%chars(), & + & key="stressStrainModel", VALUE=stressStrainModel) + + obj%stressStrainModel => NULL() obj%stressStrainModel => SolidMechanicsModelFactory( & & stressStrainModel%chars()) + CALL obj%stressStrainModel%Initiate(param) END IF @@ -102,8 +100,8 @@ MODULE PROCEDURE solid_Deallocate CALL AbstractMaterialDeallocate(obj) IF (ASSOCIATED(obj%stressStrainModel)) THEN - DEALLOCATE (obj%stressStrainModel) - NULLIFY (obj%stressStrainModel) + CALL obj%stressStrainModel%DEALLOCATE() + obj%stressStrainModel => NULL() END IF END PROCEDURE solid_Deallocate @@ -146,62 +144,4 @@ END IF END PROCEDURE Deallocate_Ptr_Vector -!---------------------------------------------------------------------------- -! solid_AddSolidMaterial -!---------------------------------------------------------------------------- - -MODULE PROCEDURE solid_AddSolidMaterial -CHARACTER(*), PARAMETER :: myName = "solid_AddSolidMaterial" - -IF (materialNo .GT. tMaterials) THEN - - CALL e%RaiseError(modName//'::'//myName//" - "// & - & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & - & '] is greater than total number of solidMaterials [='// & - & TOSTRING(tMaterials)//']!') - -END IF - -IF (PRESENT(region) .AND. PRESENT(solidMaterialToMesh)) THEN - - IF (materialNo .GT. SIZE(solidMaterialToMesh)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & - & '] is greater than the size of solidMaterialToMesh [='// & - & TOSTRING(SIZE(solidMaterialToMesh))//']!') - END IF - solidMaterialToMesh(materialNo) = region - -END IF - -IF (PRESENT(param)) THEN - - IF (materialNo .GT. SIZE(obj)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & - & '] is greater than the size of solidMaterial[='// & - & TOSTRING(SIZE(obj))//']!') - END IF - - IF (ASSOCIATED(obj(materialNo)%ptr)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & '[POINTER ERROR] :: solidMaterial('//TOSTRING(materialNo)// & - & ')%ptr is already associated.') - END IF - - IF (.NOT. PRESENT(materialName)) THEN - CALL e%RaiseError(modName//'::'//myName//" - "// & - & '[ARG MISSING] :: materialName should be present.') - END IF - - obj(materialNo)%ptr => & - & SolidMaterialFactory(TRIM(materialName)) - !! INFO: Solid material factory is defined in MaterialFactory. - - CALL obj(materialNo)%ptr%initiate(param) - -END IF - -END PROCEDURE solid_AddSolidMaterial - END SUBMODULE ConstructorMethods diff --git a/src/submodules/SolidMaterial/src/SolidMaterial_Class@SetMethods.F90 b/src/submodules/SolidMaterial/src/SolidMaterial_Class@SetMethods.F90 new file mode 100644 index 000000000..6c2c71546 --- /dev/null +++ b/src/submodules/SolidMaterial/src/SolidMaterial_Class@SetMethods.F90 @@ -0,0 +1,82 @@ +! 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(SolidMaterial_Class) SetMethods +USE BaseMethod, ONLY: ToString +USE MaterialFactory, ONLY: SolidMaterialFactory +! USE FPL_Method +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! solid_AddSolidMaterial +!---------------------------------------------------------------------------- + +MODULE PROCEDURE solid_AddSolidMaterial +CHARACTER(*), PARAMETER :: myName = "solid_AddSolidMaterial" + +IF (materialNo .GT. tMaterials) THEN + + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & + & '] is greater than total number of solidMaterials [='// & + & TOSTRING(tMaterials)//']!') + +END IF + +IF (PRESENT(region) .AND. PRESENT(solidMaterialToMesh)) THEN + + IF (materialNo .GT. SIZE(solidMaterialToMesh)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & + & '] is greater than the size of solidMaterialToMesh [='// & + & TOSTRING(SIZE(solidMaterialToMesh))//']!') + END IF + solidMaterialToMesh(materialNo) = region + +END IF + +IF (PRESENT(param)) THEN + + IF (materialNo .GT. SIZE(obj)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[OUT OF BOUND ERROR] :: Given MaterialNo [='//TOSTRING(materialNo)// & + & '] is greater than the size of solidMaterial[='// & + & TOSTRING(SIZE(obj))//']!') + END IF + + IF (ASSOCIATED(obj(materialNo)%ptr)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[POINTER ERROR] :: solidMaterial('//TOSTRING(materialNo)// & + & ')%ptr is already associated.') + END IF + + IF (.NOT. PRESENT(materialName)) THEN + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[ARG MISSING] :: materialName should be present.') + END IF + + obj(materialNo)%ptr => & + & SolidMaterialFactory(TRIM(materialName)) + !! INFO: Solid material factory is defined in MaterialFactory. + + CALL obj(materialNo)%ptr%initiate(param) + +END IF + +END PROCEDURE solid_AddSolidMaterial + +END SUBMODULE SetMethods From 7b2563a10f13b7bbfb3d01f57122640fa8a45880 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 20:04:24 +0900 Subject: [PATCH 098/117] Update LinearElasticModel_Class@getMethods.F90 Updating name from get to Get --- .../src/LinearElasticModel_Class@getMethods.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 index aaa15238d..0cdbad5d8 100644 --- a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 @@ -17,6 +17,7 @@ SUBMODULE(LinearElasticModel_Class) GetMethods IMPLICIT NONE +!! CONTAINS !---------------------------------------------------------------------------- From 11a7891520f6314d8db2d1178157e60113127664 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 20:08:30 +0900 Subject: [PATCH 099/117] Updates in LinearElasticModel_Class case sensitive issue resolved. --- .../LinearElasticModel/CMakeLists.txt | 39 +++++++++---------- ...=> LinearElasticModel_Class@GetMethod.F90} | 0 2 files changed, 19 insertions(+), 20 deletions(-) rename src/submodules/LinearElasticModel/src/{LinearElasticModel_Class@getMethods.F90 => LinearElasticModel_Class@GetMethod.F90} (100%) diff --git a/src/submodules/LinearElasticModel/CMakeLists.txt b/src/submodules/LinearElasticModel/CMakeLists.txt index ab819dbb1..635733bae 100644 --- a/src/submodules/LinearElasticModel/CMakeLists.txt +++ b/src/submodules/LinearElasticModel/CMakeLists.txt @@ -1,25 +1,24 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# 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}/LinearElasticModel_Class@ConstructorMethods.F90 - ${src_path}/LinearElasticModel_Class@IOMethods.F90 - ${src_path}/LinearElasticModel_Class@GetMethods.F90 - ${src_path}/LinearElasticModel_Class@SetMethods.F90 -) +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} + PRIVATE ${src_path}/LinearElasticModel_Class@ConstructorMethods.F90 + ${src_path}/LinearElasticModel_Class@IOMethods.F90 + ${src_path}/LinearElasticModel_Class@GetMethod.F90 + ${src_path}/LinearElasticModel_Class@SetMethods.F90) diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@GetMethod.F90 similarity index 100% rename from src/submodules/LinearElasticModel/src/LinearElasticModel_Class@getMethods.F90 rename to src/submodules/LinearElasticModel/src/LinearElasticModel_Class@GetMethod.F90 From 9fd3d41f9551498446497fef7c0bab4b976af625 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 20:09:18 +0900 Subject: [PATCH 100/117] Updates in LinearElasticModel_Class issue related to getMethods and GetMethods is resolved. --- src/submodules/LinearElasticModel/CMakeLists.txt | 2 +- ...ss@GetMethod.F90 => LinearElasticModel_Class@GetMethods.F90} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/submodules/LinearElasticModel/src/{LinearElasticModel_Class@GetMethod.F90 => LinearElasticModel_Class@GetMethods.F90} (100%) diff --git a/src/submodules/LinearElasticModel/CMakeLists.txt b/src/submodules/LinearElasticModel/CMakeLists.txt index 635733bae..914fe5e5c 100644 --- a/src/submodules/LinearElasticModel/CMakeLists.txt +++ b/src/submodules/LinearElasticModel/CMakeLists.txt @@ -20,5 +20,5 @@ target_sources( ${PROJECT_NAME} PRIVATE ${src_path}/LinearElasticModel_Class@ConstructorMethods.F90 ${src_path}/LinearElasticModel_Class@IOMethods.F90 - ${src_path}/LinearElasticModel_Class@GetMethod.F90 + ${src_path}/LinearElasticModel_Class@GetMethods.F90 ${src_path}/LinearElasticModel_Class@SetMethods.F90) diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@GetMethod.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@GetMethods.F90 similarity index 100% rename from src/submodules/LinearElasticModel/src/LinearElasticModel_Class@GetMethod.F90 rename to src/submodules/LinearElasticModel/src/LinearElasticModel_Class@GetMethods.F90 From ef1ccad3a4c65f789163c73aabcd028366c349f6 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 20:19:12 +0900 Subject: [PATCH 101/117] Fixing issue #217 Fixes issue #217 --- .../LinearPoroElasticModel/CMakeLists.txt | 39 +++++++++---------- ...inearPoroElasticModel_Class@GetMethod.F90} | 0 .../NewtonianFluidModel/CMakeLists.txt | 39 +++++++++---------- ...> NewtonianFluidModel_Class@GetMethod.F90} | 0 ...> NewtonianFluidModel_Class@SetMethod.F90} | 0 5 files changed, 38 insertions(+), 40 deletions(-) rename src/submodules/LinearPoroElasticModel/src/{LinearPoroElasticModel_Class@getMethods.F90 => LinearPoroElasticModel_Class@GetMethod.F90} (100%) rename src/submodules/NewtonianFluidModel/src/{NewtonianFluidModel_Class@getMethods.F90 => NewtonianFluidModel_Class@GetMethod.F90} (100%) rename src/submodules/NewtonianFluidModel/src/{NewtonianFluidModel_Class@setMethods.F90 => NewtonianFluidModel_Class@SetMethod.F90} (100%) diff --git a/src/submodules/LinearPoroElasticModel/CMakeLists.txt b/src/submodules/LinearPoroElasticModel/CMakeLists.txt index 8ed562436..5627fbb47 100644 --- a/src/submodules/LinearPoroElasticModel/CMakeLists.txt +++ b/src/submodules/LinearPoroElasticModel/CMakeLists.txt @@ -1,25 +1,24 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# 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}/LinearPoroElasticModel_Class@ConstructorMethods.F90 - ${src_path}/LinearPoroElasticModel_Class@IOMethods.F90 - ${src_path}/LinearPoroElasticModel_Class@GetMethods.F90 - ${src_path}/LinearPoroElasticModel_Class@SetMethods.F90 -) +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} + PRIVATE ${src_path}/LinearPoroElasticModel_Class@ConstructorMethods.F90 + ${src_path}/LinearPoroElasticModel_Class@IOMethods.F90 + ${src_path}/LinearPoroElasticModel_Class@GetMethod.F90 + ${src_path}/LinearPoroElasticModel_Class@SetMethods.F90) diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@getMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@GetMethod.F90 similarity index 100% rename from src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@getMethods.F90 rename to src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@GetMethod.F90 diff --git a/src/submodules/NewtonianFluidModel/CMakeLists.txt b/src/submodules/NewtonianFluidModel/CMakeLists.txt index bfe1ef28e..52ed95e37 100644 --- a/src/submodules/NewtonianFluidModel/CMakeLists.txt +++ b/src/submodules/NewtonianFluidModel/CMakeLists.txt @@ -1,25 +1,24 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# 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}/NewtonianFluidModel_Class@ConstructorMethods.F90 - ${src_path}/NewtonianFluidModel_Class@IOMethods.F90 - ${src_path}/NewtonianFluidModel_Class@GetMethods.F90 - ${src_path}/NewtonianFluidModel_Class@SetMethods.F90 -) +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} + PRIVATE ${src_path}/NewtonianFluidModel_Class@ConstructorMethods.F90 + ${src_path}/NewtonianFluidModel_Class@IOMethods.F90 + ${src_path}/NewtonianFluidModel_Class@GetMethod.F90 + ${src_path}/NewtonianFluidModel_Class@SetMethod.F90) diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@getMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@GetMethod.F90 similarity index 100% rename from src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@getMethods.F90 rename to src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@GetMethod.F90 diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@setMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@SetMethod.F90 similarity index 100% rename from src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@setMethods.F90 rename to src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@SetMethod.F90 From 4d6415081ae59b8f4c00ffba79d4c53f73bb9501 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 20:40:18 +0900 Subject: [PATCH 102/117] Fixing issue #217 Fixing issue #217 caused due to the merging easifemMaterial lib to easifemClasses. --- .../src/AbstractMaterialModel_Class.F90 | 70 ++++++++++--------- src/modules/CMakeLists.txt | 8 ++- src/submodules/CMakeLists.txt | 2 + 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 index f27d64ff8..966a61744 100644 --- a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 +++ b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 @@ -25,7 +25,9 @@ MODULE AbstractMaterialModel_Class USE String_Class USE ExceptionHandler_Class, ONLY: e USE HDF5File_Class +USE TxtFile_Class USE FPL, ONLY: ParameterList_ +USE tomlf, ONLY: toml_table IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractMaterialModel_Class" @@ -167,6 +169,40 @@ FUNCTION amb_GetPrefix(obj) RESULT(ans) END FUNCTION amb_GetPrefix END INTERFACE +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE + MODULE SUBROUTINE am_ImportFromToml1(obj, table) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE am_ImportFromToml1 +END INTERFACE + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE + MODULE SUBROUTINE am_ImportFromToml3(obj, tomlName, afile, filename, & + & printToml) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE am_ImportFromToml3 +END INTERFACE + !---------------------------------------------------------------------------- ! Contains !---------------------------------------------------------------------------- @@ -220,38 +256,4 @@ SUBROUTINE amb_SetName(obj, VALUE) obj%name = VALUE END SUBROUTINE amb_SetName -!---------------------------------------------------------------------------- -! ImportFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate param from the toml file - -INTERFACE AbstractMaterialImportFromToml - MODULE SUBROUTINE am_ImportFromToml1(obj, table) - CLASS(AbstractMaterial_), INTENT(INOUT) :: obj - TYPE(toml_table), INTENT(INOUT) :: table - END SUBROUTINE am_ImportFromToml1 -END INTERFACE AbstractMaterialImportFromToml - -!---------------------------------------------------------------------------- -! ImportFromToml@IOMethods -!---------------------------------------------------------------------------- - -!> author: Vikas Sharma, Ph. D. -! date: 2023-11-08 -! summary: Initiate kernel from the toml file - -INTERFACE AbstractMaterialImportFromToml - MODULE SUBROUTINE am_ImportFromToml3(obj, tomlName, afile, filename, & - & printToml) - CLASS(AbstractMaterial_), INTENT(INOUT) :: obj - CHARACTER(*), INTENT(IN) :: tomlName - TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile - CHARACTER(*), OPTIONAL, INTENT(IN) :: filename - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml - END SUBROUTINE am_ImportFromToml3 -END INTERFACE AbstractMaterialImportFromToml - END MODULE AbstractMaterialModel_Class diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 9eae32558..b9ec72406 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -318,6 +318,11 @@ include(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) # Plot include(${CMAKE_CURRENT_LIST_DIR}/Plot/CMakeLists.txt) +# easifemClasses +include(${CMAKE_CURRENT_LIST_DIR}/easifemClasses/CMakeLists.txt) + +# Materials library here + # AbstractMaterialModel include(${CMAKE_CURRENT_LIST_DIR}/AbstractMaterialModel/CMakeLists.txt) @@ -356,6 +361,3 @@ include(${CMAKE_CURRENT_LIST_DIR}/PorousMaterial/CMakeLists.txt) # easifemMaterials include(${CMAKE_CURRENT_LIST_DIR}/easifemMaterials/CMakeLists.txt) - -# easifemClasses -include(${CMAKE_CURRENT_LIST_DIR}/easifemClasses/CMakeLists.txt) diff --git a/src/submodules/CMakeLists.txt b/src/submodules/CMakeLists.txt index b5621f1cf..ee9146a3f 100644 --- a/src/submodules/CMakeLists.txt +++ b/src/submodules/CMakeLists.txt @@ -258,6 +258,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/VTKPlot/CMakeLists.txt) # PLPlot include(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) +# materials here + # AbstractSolidMechanicsModel include(${CMAKE_CURRENT_LIST_DIR}/AbstractSolidMechanicsModel/CMakeLists.txt) From cf287b6a894aa91e44acbe62983d25d69be6dd4f Mon Sep 17 00:00:00 2001 From: shion <106575883+shishiousan@users.noreply.github.com> Date: Wed, 29 Nov 2023 21:43:29 +0900 Subject: [PATCH 103/117] Fixing get and set case Fixing set and get case --- ...inearPoroElasticModel_Class@GetMethods.F90 | 71 +++++++++++++++++++ .../NewtonianFluidModel_Class@GetMethods.F90 | 59 +++++++++++++++ .../NewtonianFluidModel_Class@SetMethods.F90 | 41 +++++++++++ 3 files changed, 171 insertions(+) create mode 100644 src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@GetMethods.F90 create mode 100644 src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@GetMethods.F90 create mode 100644 src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@SetMethods.F90 diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@GetMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@GetMethods.F90 new file mode 100644 index 000000000..cb6235ebb --- /dev/null +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@GetMethods.F90 @@ -0,0 +1,71 @@ +! 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(LinearPoroElasticModel_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! lpem_GetElasticParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetElasticParam +IF (PRESENT(PoissonRatio)) PoissonRatio = obj%nu +IF (PRESENT(ShearModulus)) ShearModulus = obj%G +IF (PRESENT(YoungsModulus)) YoungsModulus = obj%E +IF (PRESENT(lambda)) lambda = obj%lambda +END PROCEDURE lpem_GetElasticParam + +!---------------------------------------------------------------------------- +! lpem_GetC +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetC +C = obj%C +END PROCEDURE lpem_GetC + +!---------------------------------------------------------------------------- +! lpem_GetInvC +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetInvC +InvC = obj%InvC +END PROCEDURE lpem_GetInvC + +!---------------------------------------------------------------------------- +! GetElasticityType +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetElasticityType +ans = obj%elasticityType +END PROCEDURE lpem_GetElasticityType + +!---------------------------------------------------------------------------- +! GetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lpem_GetParam +IF (PRESENT(elasticityType)) elasticityType = obj%elasticityType +IF (PRESENT(nu)) nu = obj%nu +IF (PRESENT(G)) G = obj%G +IF (PRESENT(youngsModulus)) youngsModulus = obj%E +IF (PRESENT(lambda)) lambda = obj%lambda +IF (PRESENT(C)) C = obj%C +IF (PRESENT(invC)) invC = obj%invC +END PROCEDURE lpem_GetParam + +END SUBMODULE GetMethods diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@GetMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@GetMethods.F90 new file mode 100644 index 000000000..d3aeb3806 --- /dev/null +++ b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@GetMethods.F90 @@ -0,0 +1,59 @@ +! 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(NewtonianFluidModel_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetDynamicViscosity +DynamicViscosity = obj%Mu +END PROCEDURE nfm_GetDynamicViscosity + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetModelParameters +INTEGER(I4B) :: ierr +IF (obj%isInitiated()) THEN + ierr = param%set(key=myprefix//"/name", & + & VALUE="NewtonianFluidModel") + ierr = param%set(key=myprefix//"/dynamicViscosity", VALUE=obj%Mu) +END IF +END PROCEDURE nfm_GetModelParameters + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetPrefix +ans = myprefix +END PROCEDURE nfm_GetPrefix + +!---------------------------------------------------------------------------- +! GetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_GetParam +IF (PRESENT(dynamicViscosity)) dynamicViscosity = obj%mu +END PROCEDURE nfm_GetParam + +END SUBMODULE GetMethods diff --git a/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@SetMethods.F90 b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@SetMethods.F90 new file mode 100644 index 000000000..31d88ab4c --- /dev/null +++ b/src/submodules/NewtonianFluidModel/src/NewtonianFluidModel_Class@SetMethods.F90 @@ -0,0 +1,41 @@ +! 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(NewtonianFluidModel_Class) SetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_SetModelParameters +INTEGER(I4B) :: ierr +IF (param%IsPresent(key=myprefix//"/dynamicViscosity")) THEN + ierr = param%Get(key=myprefix//"/dynamicViscosity", VALUE=obj%mu) +END IF +END PROCEDURE nfm_SetModelParameters + +!---------------------------------------------------------------------------- +! SetParam +!---------------------------------------------------------------------------- + +MODULE PROCEDURE nfm_SetParam +IF (PRESENT(dynamicViscosity)) obj%mu = dynamicViscosity +END PROCEDURE nfm_SetParam + +END SUBMODULE SetMethods From 479b7f9ff8fd871e20a2007d9834aa96129c7876 Mon Sep 17 00:00:00 2001 From: shion <106575883+shishiousan@users.noreply.github.com> Date: Wed, 29 Nov 2023 21:46:15 +0900 Subject: [PATCH 104/117] Updates in AbstractBC_Class In set method instead of pointer we now add target. --- src/modules/AbstractBC/src/AbstractBC_Class.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/AbstractBC/src/AbstractBC_Class.F90 b/src/modules/AbstractBC/src/AbstractBC_Class.F90 index 8aa711571..e954b98dd 100644 --- a/src/modules/AbstractBC/src/AbstractBC_Class.F90 +++ b/src/modules/AbstractBC/src/AbstractBC_Class.F90 @@ -492,7 +492,7 @@ MODULE SUBROUTINE bc_Set(obj, constantNodalValue, spaceNodalValue, & REAL(DFP), OPTIONAL, INTENT(IN) :: spaceNodalValue(:) REAL(DFP), OPTIONAL, INTENT(IN) :: timeNodalValue(:) REAL(DFP), OPTIONAL, INTENT(IN) :: spaceTimeNodalValue(:, :) - TYPE(UserFunction_), POINTER, OPTIONAL, INTENT(IN) :: userFunction + TYPE(UserFunction_), TARGET, OPTIONAL, INTENT(IN) :: userFunction END SUBROUTINE bc_Set END INTERFACE From aa0804c26e6a9d91d20f2e6b0a1f191575532e39 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 22:51:19 +0900 Subject: [PATCH 105/117] Delete AbstractField_Class.F90.findent.tmp Removing temp files --- src/modules/AbstractField/src/AbstractField_Class.F90.findent.tmp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/modules/AbstractField/src/AbstractField_Class.F90.findent.tmp diff --git a/src/modules/AbstractField/src/AbstractField_Class.F90.findent.tmp b/src/modules/AbstractField/src/AbstractField_Class.F90.findent.tmp deleted file mode 100644 index e69de29bb..000000000 From a6be878486acc09e7e2b6e6826d364b6712f977d Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Wed, 29 Nov 2023 22:52:01 +0900 Subject: [PATCH 106/117] Update in AbstractNodeField_Class Adding GetNodeLoc to AbstractNodeField class. Fixing issue #214 --- .../src/AbstractNodeField_Class.F90 | 72 ++++++++++++++++++- .../AbstractNodeField_Class@GetMethods.F90 | 30 ++++++++ 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index ec419563f..d23dcd680 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -23,6 +23,8 @@ MODULE AbstractNodeField_Class USE HDF5File_Class, ONLY: HDF5File_ USE VTKFile_Class, ONLY: VTKFile_ USE ExceptionHandler_Class, ONLY: e +USE AbstractBC_Class, ONLY: AbstractBC_ +USE DirichletBC_Class, ONLY: DirichletBCPointer_ IMPLICIT NONE PRIVATE PUBLIC :: AbstractNodeFieldDisplay @@ -125,8 +127,17 @@ MODULE AbstractNodeField_Class !! Get GetSpaceCompo PROCEDURE, PUBLIC, PASS(obj) :: GetTimeCompo => anf_GetTimeCompo !! Get the time components - - ! Set: + PROCEDURE, PUBLIC, PASS(obj) :: GetNodeLoc1 => anf_GetNodeLoc1 + !! Get location of global node number + PROCEDURE, PUBLIC, PASS(obj) :: GetNodeLoc2 => anf_GetNodeLoc2 + !! Get location of global node number from AbstractBC + PROCEDURE, PUBLIC, PASS(obj) :: GetNodeLoc3 => anf_GetNodeLoc3 + !! Get location of global node number from DirichletBCPointer + GENERIC, PUBLIC :: GetNodeLoc => GetNodeLoc1, GetNodeLoc2, & + & GetNodeLoc3 + !! Generic method for getting location of nodes + + ! SET: ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: SetSingle => anf_SetSingle !! Set single entry @@ -479,6 +490,63 @@ MODULE FUNCTION anf_Size(obj, dims) RESULT(ans) END FUNCTION anf_Size END INTERFACE +!---------------------------------------------------------------------------- +! GetNodeLoc@GeMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-29 +! summary: This function returns the location of globalNode + +INTERFACE + MODULE FUNCTION anf_GetNodeLoc1(obj, globalNode, ivar, spaceCompo, & + & timeCompo) RESULT(ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + INTEGER(I4B), INTENT(IN) :: globalNode(:) + !! Global node number + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + !! physical varibale number + INTEGER(I4B), OPTIONAL, INTENT(IN) :: spaceCompo(:) + !! list of space components + INTEGER(I4B), OPTIONAL, INTENT(IN) :: timeCompo(:) + !! list of time components + END FUNCTION anf_GetNodeLoc1 +END INTERFACE + +!---------------------------------------------------------------------------- +! GetNodeLoc@GeMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-29 +! summary: This function returns the location of globalNode from bc + +INTERFACE + MODULE FUNCTION anf_GetNodeLoc2(obj, dbc, ivar) RESULT(ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + CLASS(AbstractBC_), INTENT(INOUT) :: dbc + !! Global node number + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END FUNCTION anf_GetNodeLoc2 +END INTERFACE + +!---------------------------------------------------------------------------- +! GetNodeLoc@GeMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-29 +! summary: This function returns the location of globalNode from bc + +INTERFACE + MODULE FUNCTION anf_GetNodeLoc3(obj, dbc, ivar) RESULT(ans) + CLASS(AbstractNodeField_), INTENT(IN) :: obj + TYPE(DirichletBCPointer_), INTENT(INOUT) :: dbc(:) + !! Global node number + INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + END FUNCTION anf_GetNodeLoc3 +END INTERFACE + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 index ec277e8ad..d2fb7edb1 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 @@ -203,6 +203,36 @@ END IF END PROCEDURE anf_GetSingle +!---------------------------------------------------------------------------- +! GetNodeLoc +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetNodeLoc1 +CHARACTER(*), PARAMETER :: myName = "anf_GetNodeLoc1()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine is under development.') +END PROCEDURE anf_GetNodeLoc1 + +!---------------------------------------------------------------------------- +! GetNodeLoc +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetNodeLoc2 +CHARACTER(*), PARAMETER :: myName = "anf_GetNodeLoc2()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine is under development.') +END PROCEDURE anf_GetNodeLoc2 + +!---------------------------------------------------------------------------- +! GetNodeLoc +!---------------------------------------------------------------------------- + +MODULE PROCEDURE anf_GetNodeLoc3 +CHARACTER(*), PARAMETER :: myName = "anf_GetNodeLoc3()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine is under development.') +END PROCEDURE anf_GetNodeLoc3 + !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- From 2ccb196ba7374b51601317a6b05a0b006253b2ab Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 01:05:55 +0900 Subject: [PATCH 107/117] Adding GetNodeLoc to AbstractNodeField Fixes issue #214 --- .../src/AbstractNodeField_Class.F90 | 3 + .../AbstractNodeField_Class@GetMethods.F90 | 133 +++++++++++++++++- 2 files changed, 130 insertions(+), 6 deletions(-) diff --git a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 index d23dcd680..351b6d773 100644 --- a/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 +++ b/src/modules/AbstractNodeField/src/AbstractNodeField_Class.F90 @@ -510,6 +510,7 @@ MODULE FUNCTION anf_GetNodeLoc1(obj, globalNode, ivar, spaceCompo, & !! list of space components INTEGER(I4B), OPTIONAL, INTENT(IN) :: timeCompo(:) !! list of time components + INTEGER(I4B), ALLOCATABLE :: ans(:) END FUNCTION anf_GetNodeLoc1 END INTERFACE @@ -527,6 +528,7 @@ MODULE FUNCTION anf_GetNodeLoc2(obj, dbc, ivar) RESULT(ans) CLASS(AbstractBC_), INTENT(INOUT) :: dbc !! Global node number INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + INTEGER(I4B), ALLOCATABLE :: ans(:) END FUNCTION anf_GetNodeLoc2 END INTERFACE @@ -544,6 +546,7 @@ MODULE FUNCTION anf_GetNodeLoc3(obj, dbc, ivar) RESULT(ans) TYPE(DirichletBCPointer_), INTENT(INOUT) :: dbc(:) !! Global node number INTEGER(I4B), OPTIONAL, INTENT(IN) :: ivar + INTEGER(I4B), ALLOCATABLE :: ans(:) END FUNCTION anf_GetNodeLoc3 END INTERFACE diff --git a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 index d2fb7edb1..6a1eaf958 100644 --- a/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 +++ b/src/submodules/AbstractNodeField/src/AbstractNodeField_Class@GetMethods.F90 @@ -209,8 +209,86 @@ MODULE PROCEDURE anf_GetNodeLoc1 CHARACTER(*), PARAMETER :: myName = "anf_GetNodeLoc1()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine is under development.') +INTEGER(I4B), ALLOCATABLE :: spaceCompo0(:), timeCompo0(:), localNode(:) +INTEGER(I4B) :: ivar0, tsize, itime, ttime +TYPE(IntVector_), ALLOCATABLE :: int_vec_list(:) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GetNodeLoc1()') +#endif + +IF (PRESENT(spaceCompo)) THEN + tsize = SIZE(spaceCompo) + CALL Reallocate(spaceCompo0, tsize) + spaceCompo0 = spaceCompo +ELSE + CALL Reallocate(spaceCompo0, 1) + spaceCompo0 = 1 +END IF + +IF (PRESENT(timeCompo)) THEN + tsize = SIZE(timeCompo) + CALL Reallocate(timeCompo0, tsize) + timeCompo0 = timeCompo +ELSE + CALL Reallocate(timeCompo0, 1) + timeCompo0 = 1 +END IF +ttime = SIZE(timeCompo0) + +IF (PRESENT(ivar)) THEN + ivar0 = ivar +ELSE + ivar0 = 1 +END IF + +ALLOCATE (int_vec_list(ttime)) +CALL Reallocate(localNode, SIZE(globalNode)) + +IF (ASSOCIATED(obj%domain)) THEN + + localNode = obj%domain%GetLocalNodeNumber(globalNode=globalNode) + +ELSEIF (ALLOCATED(obj%domains)) THEN + tsize = SIZE(obj%domains) + IF (ivar0 .GT. tsize) THEN + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: ivar is greater than size of '// & + & ' AbstractNodeField_::obj%domains.') + RETURN + END IF + localNode = obj%domains(ivar0)%ptr%GetLocalNodeNumber(globalNode) + +ELSE + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] :: AbstractNodeField_::obj%domain '// & + & ' obj%domains are not allocated.') + RETURN +END IF + +DO itime = 1, ttime + int_vec_list(itime) = GetNodeLoc(obj=obj%dof, nodenum=localNode, & + & ivar=ivar0, spaceCompo=spaceCompo0, timeCompo=timeCompo0(itime)) +END DO + +ans = Get(obj=int_vec_list, dataType=1_I4B) + +IF (ALLOCATED(int_vec_list)) THEN + DO itime = 1, ttime + CALL DEALLOCATE (int_vec_list(itime)) + END DO + DEALLOCATE (int_vec_list) +END IF + +IF (ALLOCATED(spaceCompo0)) DEALLOCATE (spaceCompo0) +IF (ALLOCATED(timeCompo0)) DEALLOCATE (timeCompo0) +IF (ALLOCATED(localNode)) DEALLOCATE (localNode) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GetNodeLoc1()') +#endif END PROCEDURE anf_GetNodeLoc1 !---------------------------------------------------------------------------- @@ -219,8 +297,31 @@ MODULE PROCEDURE anf_GetNodeLoc2 CHARACTER(*), PARAMETER :: myName = "anf_GetNodeLoc2()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine is under development.') +INTEGER(I4B), ALLOCATABLE :: globalNode(:), timeCompo(:) +INTEGER(I4B) :: tPhysicalVars, spaceCompo(1), ivar0 + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GetNodeLoc2()') +#endif + +tPhysicalVars = obj%GetTotalPhysicalVars() +CALL Reallocate(timeCompo, tPhysicalVars) +timeCompo = obj%GetTimeCompo(tPhysicalVars) +spaceCompo(1) = dbc%GetDOFNo() +ivar0 = input(default=1_I4B, option=ivar) + +CALL dbc%Get(nodeNum=globalNode) +ans = obj%GetNodeLoc(globalNode=globalNode, ivar=ivar, & + & spaceCompo=spaceCompo, timeCompo=arange(1_I4B, timeCompo(ivar0))) + +IF (ALLOCATED(globalNode)) DEALLOCATE (globalNode) +IF (ALLOCATED(timeCompo)) DEALLOCATE (timeCompo) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GetNodeLoc2()') +#endif END PROCEDURE anf_GetNodeLoc2 !---------------------------------------------------------------------------- @@ -229,8 +330,28 @@ MODULE PROCEDURE anf_GetNodeLoc3 CHARACTER(*), PARAMETER :: myName = "anf_GetNodeLoc3()" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine is under development.') +INTEGER(I4B) :: ii, tsize +INTEGER(I4B), ALLOCATABLE :: nptrs(:) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] GetNodeLoc3()') +#endif + +tsize = SIZE(dbc) + +DO ii = 1, tsize + nptrs = obj%GetNodeLoc(dbc=dbc(ii)%ptr, ivar=ivar) + CALL Append(ans, nptrs) +END DO + +IF (ALLOCATED(nptrs)) DEALLOCATE (nptrs) + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] GetNodeLoc3()') +#endif + END PROCEDURE anf_GetNodeLoc3 !---------------------------------------------------------------------------- From 4cb4ac46797bd55505f389862a6652a0fd45faf8 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 12:12:12 +0900 Subject: [PATCH 108/117] Updates in AbstractSolidMechanicsModel Adding new module structure in AbstractSolidMechanicsModel --- .../src/AbstractSolidMechanicsModel_Class.F90 | 167 +++++++++++++----- .../CMakeLists.txt | 36 ++-- ...echanicsModel_Class@ConstructorMethods.F90 | 54 ++++++ ...tSolidMechanicsModel_Class@GetMethods.F90} | 86 ++------- ...actSolidMechanicsModel_Class@IOMethods.F90 | 75 ++++++++ ...ctSolidMechanicsModel_Class@SetMethods.F90 | 38 ++++ 6 files changed, 322 insertions(+), 134 deletions(-) create mode 100644 src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@ConstructorMethods.F90 rename src/submodules/AbstractSolidMechanicsModel/src/{AbstractSolidMechanicsModel_Class@Methods.F90 => AbstractSolidMechanicsModel_Class@GetMethods.F90} (58%) create mode 100644 src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@IOMethods.F90 create mode 100644 src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@SetMethods.F90 diff --git a/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 b/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 index 2a9b25602..fe6ef94d7 100644 --- a/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 +++ b/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 @@ -27,6 +27,8 @@ MODULE AbstractSolidMechanicsModel_Class USE HDF5File_Class USE FPL, ONLY: ParameterList_ USE AbstractMaterialModel_Class +USE tomlf, ONLY: toml_table +USE TxtFile_Class, ONLY: TxtFile_ IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractSolidMechanicsModel_Class" @@ -51,13 +53,24 @@ MODULE AbstractSolidMechanicsModel_Class !! PlaneStrain CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & lem_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate => lem_Initiate PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => lem_Deallocate + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => lem_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => lem_Export PROCEDURE, PUBLIC, PASS(obj) :: Display => lem_Display + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml1 => lem_ImportFromToml1 + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml2 => lem_ImportFromToml2 + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetElasticParam => lem_GetElasticParam PROCEDURE, PUBLIC, PASS(obj) :: GetC => lem_GetC PROCEDURE, PUBLIC, PASS(obj) :: GetInvC => lem_GetInvC @@ -66,6 +79,9 @@ MODULE AbstractSolidMechanicsModel_Class PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => lem_GetPrefix PROCEDURE, PUBLIC, PASS(obj) :: isPlaneStrain => lem_isPlaneStrain PROCEDURE, PUBLIC, PASS(obj) :: isPlaneStress => lem_isPlaneStress + + ! SET: + ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: SetPlaneStress => lem_SetPlaneStress PROCEDURE, PUBLIC, PASS(obj) :: SetPlaneStrain => lem_SetPlaneStrain END TYPE AbstractSolidMechanicsModel_ @@ -91,7 +107,7 @@ END SUBROUTINE lem_CheckEssentialParam !> authors: Vikas Sharma, Ph. D. ! date: 27 Aug 2021 -! summary: This routine initiates the the Linear elastic model +! summary: This routine initiates the model INTERFACE MODULE SUBROUTINE lem_Initiate(obj, param) @@ -106,13 +122,13 @@ END SUBROUTINE lem_Initiate !> authors: Vikas Sharma, Ph. D. ! date: 27 Aug 2021 -! summary: Deallocate data +! summary: Deallocate data -INTERFACE +INTERFACE AbstractSolidMechanicsModelDeallocate MODULE SUBROUTINE lem_Deallocate(obj) CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj END SUBROUTINE lem_Deallocate -END INTERFACE +END INTERFACE AbstractSolidMechanicsModelDeallocate !---------------------------------------------------------------------------- ! Import@IOMethods @@ -120,7 +136,7 @@ END SUBROUTINE lem_Deallocate !> authors: Vikas Sharma, Ph. D. ! date: 27 Aug 2021 -! summary: Initiate the linear elastic model by import +! summary: Initiate the model by import INTERFACE MODULE SUBROUTINE lem_Import(obj, hdf5, group) @@ -136,7 +152,7 @@ END SUBROUTINE lem_Import !> authors: Vikas Sharma, Ph. D. ! date: 27 Aug 2021 -! summary: Export the linear elastic model +! summary: Export the model INTERFACE MODULE SUBROUTINE lem_Export(obj, hdf5, group) @@ -152,7 +168,7 @@ END SUBROUTINE lem_Export !> authors: Vikas Sharma, Ph. D. ! date: 27 Aug 2021 -! summary: Displays the content of linear elastic model +! summary: Displays the content of model INTERFACE MODULE SUBROUTINE lem_Display(obj, msg, unitNo) @@ -162,18 +178,56 @@ MODULE SUBROUTINE lem_Display(obj, msg, unitNo) END SUBROUTINE lem_Display END INTERFACE +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate param from the toml file + +INTERFACE + MODULE SUBROUTINE lem_ImportFromToml1(obj, table) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + TYPE(toml_table), INTENT(INOUT) :: table + END SUBROUTINE lem_ImportFromToml1 +END INTERFACE + +!---------------------------------------------------------------------------- +! ImportFromToml@IOMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-08 +! summary: Initiate kernel from the toml file + +INTERFACE + MODULE SUBROUTINE lem_ImportFromToml2(obj, tomlName, afile, filename, & + & printToml) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: tomlName + TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile + CHARACTER(*), OPTIONAL, INTENT(IN) :: filename + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml + END SUBROUTINE lem_ImportFromToml2 +END INTERFACE + !---------------------------------------------------------------------------- ! GetElasticParam@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get elastic parameter + INTERFACE - MODULE SUBROUTINE lem_GetElasticParam(obj, PoissonRatio, & - & ShearModulus, lambda, YoungsModulus, stiffnessPower) + MODULE SUBROUTINE lem_GetElasticParam(obj, poissonRatio, & + & shearModulus, lambda, youngsModulus, stiffnessPower) CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj - REAL(DFP), OPTIONAL, INTENT(INOUT) :: PoissonRatio - REAL(DFP), OPTIONAL, INTENT(INOUT) :: ShearModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: poissonRatio + REAL(DFP), OPTIONAL, INTENT(INOUT) :: shearModulus REAL(DFP), OPTIONAL, INTENT(INOUT) :: lambda - REAL(DFP), OPTIONAL, INTENT(INOUT) :: YoungsModulus + REAL(DFP), OPTIONAL, INTENT(INOUT) :: youngsModulus REAL(DFP), OPTIONAL, INTENT(INOUT) :: stiffnessPower END SUBROUTINE lem_GetElasticParam END INTERFACE @@ -182,6 +236,10 @@ END SUBROUTINE lem_GetElasticParam ! GetC@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get the elastic tangent matrix + INTERFACE MODULE SUBROUTINE lem_GetC(obj, C) CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj @@ -193,10 +251,14 @@ END SUBROUTINE lem_GetC ! GetC@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get inverse of elastic tangent matrix + INTERFACE MODULE SUBROUTINE lem_GetInvC(obj, InvC) CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj - REAL(DFP), INTENT(INOUT) :: InvC(:, :) + REAL(DFP), INTENT(INOUT) :: invC(:, :) END SUBROUTINE lem_GetInvC END INTERFACE @@ -204,6 +266,10 @@ END SUBROUTINE lem_GetInvC ! GetElasticityType@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get elasticity type + INTERFACE MODULE FUNCTION lem_GetElasticityType(obj) RESULT(Ans) CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj @@ -212,9 +278,13 @@ END FUNCTION lem_GetElasticityType END INTERFACE !---------------------------------------------------------------------------- -! GetPrefix +! GetPrefix@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get prefix + INTERFACE MODULE FUNCTION lem_GetPrefix(obj) RESULT(ans) CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj @@ -223,56 +293,55 @@ END FUNCTION lem_GetPrefix END INTERFACE !---------------------------------------------------------------------------- -! Contains +! isPlaneStress@GetMethods !---------------------------------------------------------------------------- -CONTAINS +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Returns true if the problem is plane stress -SUBROUTINE AbstractSolidMechanicsModelDeallocate(obj) - CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj - CALL AbstractMaterialModelDeallocate(obj) - obj%isPStress = .FALSE. - obj%isPStrain = .FALSE. -END SUBROUTINE AbstractSolidMechanicsModelDeallocate +INTERFACE + MODULE FUNCTION lem_isPlaneStress(obj) RESULT(ans) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + END FUNCTION lem_isPlaneStress +END INTERFACE !---------------------------------------------------------------------------- -! isPlaneStress +! isPlaneStrain@GetMethods !---------------------------------------------------------------------------- -FUNCTION lem_isPlaneStress(obj) RESULT(ans) - CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj - LOGICAL(LGT) :: ans - ans = obj%isPStress -END FUNCTION lem_isPlaneStress +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Returns true if the problem is plane strain -!---------------------------------------------------------------------------- -! isPlaneStrain -!---------------------------------------------------------------------------- - -FUNCTION lem_isPlaneStrain(obj) RESULT(ans) - CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj - LOGICAL(LGT) :: ans - ans = obj%isPStrain -END FUNCTION lem_isPlaneStrain +INTERFACE + MODULE FUNCTION lem_isPlaneStrain(obj) RESULT(ans) + CLASS(AbstractSolidMechanicsModel_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + END FUNCTION lem_isPlaneStrain +END INTERFACE !---------------------------------------------------------------------------- -! SetPlaneStress +! SetPlaneStress@SetMethods !---------------------------------------------------------------------------- -SUBROUTINE lem_SetPlaneStress(obj, VALUE) - CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj - LOGICAL(LGT), INTENT(IN) :: VALUE - obj%isPStress = VALUE -END SUBROUTINE lem_SetPlaneStress +INTERFACE + MODULE SUBROUTINE lem_SetPlaneStress(obj, VALUE) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: VALUE + END SUBROUTINE lem_SetPlaneStress +END INTERFACE !---------------------------------------------------------------------------- -! SetPlaneStrain +! SetPlaneStrain@SetMethods !---------------------------------------------------------------------------- -SUBROUTINE lem_SetPlaneStrain(obj, VALUE) - CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj - LOGICAL(LGT), INTENT(IN) :: VALUE - obj%isPStrain = VALUE -END SUBROUTINE lem_SetPlaneStrain +INTERFACE + MODULE SUBROUTINE lem_SetPlaneStrain(obj, VALUE) + CLASS(AbstractSolidMechanicsModel_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: VALUE + END SUBROUTINE lem_SetPlaneStrain +END INTERFACE END MODULE AbstractSolidMechanicsModel_Class diff --git a/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt b/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt index 0c5653565..437eb7abb 100644 --- a/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt +++ b/src/submodules/AbstractSolidMechanicsModel/CMakeLists.txt @@ -1,22 +1,24 @@ -# This program is a part of EASIFEM library -# Copyright (C) 2020-2021 Vikas Sharma, Ph.D +# 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 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. +# 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 +# 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}/AbstractSolidMechanicsModel_Class@Methods.F90 -) +set(src_path "${CMAKE_CURRENT_LIST_DIR}/src/") +target_sources( + ${PROJECT_NAME} + PRIVATE ${src_path}/AbstractSolidMechanicsModel_Class@SetMethods.F90 + ${src_path}/AbstractSolidMechanicsModel_Class@GetMethods.F90 + ${src_path}/AbstractSolidMechanicsModel_Class@IOMethods.F90 + ${src_path}/AbstractSolidMechanicsModel_Class@ConstructorMethods.F90) diff --git a/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@ConstructorMethods.F90 b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..4e72cb895 --- /dev/null +++ b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@ConstructorMethods.F90 @@ -0,0 +1,54 @@ +! 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(AbstractSolidMechanicsModel_Class) ConstructorMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "lem_CheckEssentialParam" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of'// & + & CHAR_LF//'AbstractSolidMechanicsModel_') +END PROCEDURE lem_CheckEssentialParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Initiate +CHARACTER(*), PARAMETER :: myName = "lem_Initiate" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & CHAR_LF//'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Initiate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Deallocate +CALL AbstractMaterialModelDeallocate(obj) +obj%isPStress = .FALSE. +obj%isPStrain = .FALSE. +END PROCEDURE lem_Deallocate + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@GetMethods.F90 similarity index 58% rename from src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 rename to src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@GetMethods.F90 index 4a2541ef1..4b5c24383 100644 --- a/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@Methods.F90 +++ b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@GetMethods.F90 @@ -15,7 +15,7 @@ ! along with this program. If not, see ! -SUBMODULE(AbstractSolidMechanicsModel_Class) Methods +SUBMODULE(AbstractSolidMechanicsModel_Class) GetMethods IMPLICIT NONE CONTAINS @@ -23,72 +23,6 @@ ! !---------------------------------------------------------------------------- -MODULE PROCEDURE lem_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "lem_CheckEssentialParam" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child of'// & - & CHAR_LF//'AbstractSolidMechanicsModel_') -END PROCEDURE lem_CheckEssentialParam - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE lem_Initiate -CHARACTER(*), PARAMETER :: myName = "lem_Initiate" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child of '// & - & CHAR_LF//'AbstractSolidMechanicsModel_') -END PROCEDURE lem_Initiate - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE lem_Deallocate -CHARACTER(*), PARAMETER :: myName = "lem_Deallocate" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child of '// & - & 'AbstractSolidMechanicsModel_') -END PROCEDURE lem_Deallocate - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE lem_Import -CHARACTER(*), PARAMETER :: myName = "lem_Import" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child of '// & - & 'AbstractSolidMechanicsModel_') -END PROCEDURE lem_Import - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE lem_Export -CHARACTER(*), PARAMETER :: myName = "lem_Export" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child of '// & - & 'AbstractSolidMechanicsModel_') -END PROCEDURE lem_Export - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - -MODULE PROCEDURE lem_Display -CHARACTER(*), PARAMETER :: myName = "lem_Display" -CALL e%RaiseError(modName//'::'//myName//' - '// & - & '[WIP ERROR] :: This routine should be implemented by child of '// & - & 'AbstractSolidMechanicsModel_') -END PROCEDURE lem_Display - -!---------------------------------------------------------------------------- -! -!---------------------------------------------------------------------------- - MODULE PROCEDURE lem_GetElasticParam CHARACTER(*), PARAMETER :: myName = "lem_GetElasticParam()" CALL e%RaiseError(modName//'::'//myName//' - '// & @@ -144,4 +78,20 @@ ans = "" END PROCEDURE lem_GetPrefix -END SUBMODULE Methods +!---------------------------------------------------------------------------- +! isPlaneStress +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_isPlaneStress +ans = obj%isPStress +END PROCEDURE lem_isPlaneStress + +!---------------------------------------------------------------------------- +! isPlaneStrain +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_isPlaneStrain +ans = obj%isPStrain +END PROCEDURE lem_isPlaneStrain + +END SUBMODULE GetMethods diff --git a/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@IOMethods.F90 b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@IOMethods.F90 new file mode 100644 index 000000000..a4b700136 --- /dev/null +++ b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@IOMethods.F90 @@ -0,0 +1,75 @@ +! 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(AbstractSolidMechanicsModel_Class) IOMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Import +CHARACTER(*), PARAMETER :: myName = "lem_Import" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Export +CHARACTER(*), PARAMETER :: myName = "lem_Export" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Export + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_Display +CHARACTER(*), PARAMETER :: myName = "lem_Display" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE lem_Display + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "lem_ImportFromToml1()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This method is under development.') +END PROCEDURE lem_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "lem_ImportFromToml2()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This method is under development.') +END PROCEDURE lem_ImportFromToml2 + +END SUBMODULE IOMethods diff --git a/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@SetMethods.F90 b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@SetMethods.F90 new file mode 100644 index 000000000..e0c73ebc9 --- /dev/null +++ b/src/submodules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class@SetMethods.F90 @@ -0,0 +1,38 @@ +! 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(AbstractSolidMechanicsModel_Class) SetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetPlaneStress +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_SetPlaneStress +obj%isPStress = VALUE +END PROCEDURE lem_SetPlaneStress + +!---------------------------------------------------------------------------- +! SetPlaneStrain +!---------------------------------------------------------------------------- + +MODULE PROCEDURE lem_SetPlaneStrain +obj%isPStrain = VALUE +END PROCEDURE lem_SetPlaneStrain + +END SUBMODULE SetMethods From e45999c14d0a39567ddd8676c339693bac268b08 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 15:45:26 +0900 Subject: [PATCH 109/117] Updates in AbstractMaterialModel New module structure in abstract material model. --- .../src/AbstractMaterialModel_Class.F90 | 190 ++++++++++-------- .../AbstractMaterialModel/CMakeLists.txt | 24 +++ ...MaterialModel_Class@ConstructorMethods.F90 | 53 +++++ ...AbstractMaterialModel_Class@GetMethods.F90 | 50 +++++ .../AbstractMaterialModel_Class@IOMethods.F90 | 75 +++++++ ...AbstractMaterialModel_Class@SetMethods.F90 | 38 ++++ src/submodules/CMakeLists.txt | 3 + 7 files changed, 345 insertions(+), 88 deletions(-) create mode 100644 src/submodules/AbstractMaterialModel/CMakeLists.txt create mode 100644 src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@ConstructorMethods.F90 create mode 100644 src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 create mode 100644 src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@IOMethods.F90 create mode 100644 src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 diff --git a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 index 966a61744..0cd780713 100644 --- a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 +++ b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 @@ -51,28 +51,30 @@ MODULE AbstractMaterialModel_Class ! CONSTRUCTOR: ! @ConstructorMethods - PROCEDURE(amb_CheckEssentialParam), DEFERRED, PUBLIC, PASS(obj) :: & - & CheckEssentialParam - PROCEDURE(amb_Initiate), DEFERRED, PUBLIC, PASS(obj) :: Initiate - PROCEDURE(amb_Deallocate), DEFERRED, PUBLIC, PASS(obj) :: & - & DEALLOCATE - PROCEDURE, PUBLIC, PASS(obj) :: isInitiated => amb_isInitiated + PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & + & obj_CheckEssentialParam + PROCEDURE, PUBLIC, PASS(obj) :: Initiate => obj_Initiate + PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => obj_Deallocate ! IO: ! @IOMethods - PROCEDURE(amb_Import), DEFERRED, PUBLIC, PASS(obj) :: IMPORT - PROCEDURE(amb_Export), DEFERRED, PUBLIC, PASS(obj) :: Export - PROCEDURE(amb_Display), DEFERRED, PUBLIC, PASS(obj) :: Display + PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => obj_Import + PROCEDURE, PUBLIC, PASS(obj) :: Export => obj_Export + PROCEDURE, PUBLIC, PASS(obj) :: Display => obj_Display + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml1 => obj_ImportFromToml1 + PROCEDURE, PUBLIC, PASS(obj) :: ImportFromToml2 => obj_ImportFromToml2 + GENERIC, PUBLIC :: ImportFromToml => ImportFromToml1, ImportFromToml2 ! GET: ! @GetMethods - PROCEDURE(amb_GetPrefix), DEFERRED, PUBLIC, PASS(obj) :: GetPrefix - PROCEDURE, PUBLIC, PASS(obj) :: GetName => amb_GetName + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => obj_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: GetName => obj_GetName + PROCEDURE, PUBLIC, PASS(obj) :: isInitiated => obj_isInitiated ! SET: ! @SetMethods - PROCEDURE, PUBLIC, PASS(obj) :: SetIsInitiated => amb_SetIsInitiated - PROCEDURE, PUBLIC, PASS(obj) :: SetName => amb_SetName + PROCEDURE, PUBLIC, PASS(obj) :: SetIsInitiated => obj_SetIsInitiated + PROCEDURE, PUBLIC, PASS(obj) :: SetName => obj_SetName END TYPE AbstractMaterialModel_ !---------------------------------------------------------------------------- @@ -84,89 +86,95 @@ MODULE AbstractMaterialModel_Class END TYPE AbstractMaterialModelPointer_ !---------------------------------------------------------------------------- -! CheckEssentialParam +! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- -ABSTRACT INTERFACE - SUBROUTINE amb_CheckEssentialParam(obj, param) - IMPORT :: AbstractMaterialModel_, ParameterList_ +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Check the essential parameters + +INTERFACE + MODULE SUBROUTINE obj_CheckEssentialParam(obj, param) CLASS(AbstractMaterialModel_), INTENT(IN) :: obj TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE amb_CheckEssentialParam + END SUBROUTINE obj_CheckEssentialParam END INTERFACE !---------------------------------------------------------------------------- ! Initiate !---------------------------------------------------------------------------- -ABSTRACT INTERFACE - SUBROUTINE amb_Initiate(obj, param) - IMPORT :: AbstractMaterialModel_, ParameterList_ +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Initiate an instance of AbstractMaterialModel_ + +INTERFACE + MODULE SUBROUTINE obj_Initiate(obj, param) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param - END SUBROUTINE amb_Initiate + END SUBROUTINE obj_Initiate END INTERFACE !---------------------------------------------------------------------------- ! Deallocate !---------------------------------------------------------------------------- -ABSTRACT INTERFACE - SUBROUTINE amb_Deallocate(obj) - IMPORT :: AbstractMaterialModel_ +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Deallocate the data stored in AbstractMaterialModel_ + +INTERFACE AbstractMaterialModelDeallocate + MODULE SUBROUTINE obj_Deallocate(obj) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj - END SUBROUTINE amb_Deallocate -END INTERFACE + END SUBROUTINE obj_Deallocate +END INTERFACE AbstractMaterialModelDeallocate !---------------------------------------------------------------------------- ! Import !---------------------------------------------------------------------------- -ABSTRACT INTERFACE - SUBROUTINE amb_Import(obj, hdf5, group) - IMPORT :: AbstractMaterialModel_, HDF5File_ +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Import data from the HDF5File + +INTERFACE + MODULE SUBROUTINE obj_Import(obj, hdf5, group) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - END SUBROUTINE amb_Import + END SUBROUTINE obj_Import END INTERFACE !---------------------------------------------------------------------------- ! Export !---------------------------------------------------------------------------- -ABSTRACT INTERFACE - SUBROUTINE amb_Export(obj, hdf5, group) - IMPORT :: AbstractMaterialModel_, HDF5File_ +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Export the data into HDF5File + +INTERFACE + MODULE SUBROUTINE obj_Export(obj, hdf5, group) CLASS(AbstractMaterialModel_), INTENT(IN) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group - END SUBROUTINE amb_Export + END SUBROUTINE obj_Export END INTERFACE !---------------------------------------------------------------------------- ! Display !---------------------------------------------------------------------------- -ABSTRACT INTERFACE - SUBROUTINE amb_Display(obj, msg, unitNo) - IMPORT :: AbstractMaterialModel_, I4B +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Display the content + +INTERFACE + MODULE SUBROUTINE obj_Display(obj, msg, unitNo) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo - END SUBROUTINE amb_Display -END INTERFACE - -!---------------------------------------------------------------------------- -! GetPrefix -!---------------------------------------------------------------------------- - -ABSTRACT INTERFACE - FUNCTION amb_GetPrefix(obj) RESULT(ans) - IMPORT :: AbstractMaterialModel_ - CLASS(AbstractMaterialModel_), INTENT(IN) :: obj - CHARACTER(:), ALLOCATABLE :: ans - END FUNCTION amb_GetPrefix + END SUBROUTINE obj_Display END INTERFACE !---------------------------------------------------------------------------- @@ -178,10 +186,10 @@ END FUNCTION amb_GetPrefix ! summary: Initiate param from the toml file INTERFACE - MODULE SUBROUTINE am_ImportFromToml1(obj, table) + MODULE SUBROUTINE obj_ImportFromToml1(obj, table) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj TYPE(toml_table), INTENT(INOUT) :: table - END SUBROUTINE am_ImportFromToml1 + END SUBROUTINE obj_ImportFromToml1 END INTERFACE !---------------------------------------------------------------------------- @@ -193,67 +201,73 @@ END SUBROUTINE am_ImportFromToml1 ! summary: Initiate kernel from the toml file INTERFACE - MODULE SUBROUTINE am_ImportFromToml3(obj, tomlName, afile, filename, & + MODULE SUBROUTINE obj_ImportFromToml2(obj, tomlName, afile, filename, & & printToml) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: tomlName TYPE(TxtFile_), OPTIONAL, INTENT(INOUT) :: afile CHARACTER(*), OPTIONAL, INTENT(IN) :: filename LOGICAL(LGT), OPTIONAL, INTENT(IN) :: printToml - END SUBROUTINE am_ImportFromToml3 + END SUBROUTINE obj_ImportFromToml2 END INTERFACE !---------------------------------------------------------------------------- -! Contains +! SetIsInitiated@SetMethods !---------------------------------------------------------------------------- -CONTAINS - -SUBROUTINE AbstractMaterialModelDeallocate(obj) - CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj - obj%name = "" - obj%isInit = .FALSE. -END SUBROUTINE AbstractMaterialModelDeallocate +INTERFACE + MODULE SUBROUTINE obj_SetIsInitiated(obj, VALUE) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + LOGICAL(LGT), INTENT(IN) :: VALUE + END SUBROUTINE obj_SetIsInitiated +END INTERFACE !---------------------------------------------------------------------------- -! GetName +! SetName !---------------------------------------------------------------------------- -FUNCTION amb_GetName(obj) RESULT(ans) - CLASS(AbstractMaterialModel_), INTENT(IN) :: obj - CHARACTER(:), ALLOCATABLE :: ans - ans = "" - ans = obj%name%chars() -END FUNCTION amb_GetName +INTERFACE + MODULE SUBROUTINE obj_SetName(obj, VALUE) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + CHARACTER(*), INTENT(IN) :: VALUE + END SUBROUTINE obj_SetName +END INTERFACE !---------------------------------------------------------------------------- -! isInitiated +! GetPrefix !---------------------------------------------------------------------------- -FUNCTION amb_isInitiated(obj) RESULT(ans) - CLASS(AbstractMaterialModel_), INTENT(IN) :: obj - LOGICAL(LGT) :: ans - ans = obj%isInit -END FUNCTION amb_isInitiated +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get prefix + +INTERFACE + MODULE FUNCTION obj_GetPrefix(obj) RESULT(ans) + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION obj_GetPrefix +END INTERFACE !---------------------------------------------------------------------------- -! isInitiated +! GetName !---------------------------------------------------------------------------- -SUBROUTINE amb_SetIsInitiated(obj, VALUE) - CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj - LOGICAL(LGT), INTENT(IN) :: VALUE - obj%isInit = VALUE -END SUBROUTINE amb_SetIsInitiated +INTERFACE + MODULE FUNCTION obj_GetName(obj) RESULT(ans) + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION obj_GetName +END INTERFACE !---------------------------------------------------------------------------- -! SetName +! isInitiated !---------------------------------------------------------------------------- -SUBROUTINE amb_SetName(obj, VALUE) - CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj - CHARACTER(*), INTENT(IN) :: VALUE - obj%name = VALUE -END SUBROUTINE amb_SetName +INTERFACE + MODULE FUNCTION obj_isInitiated(obj) RESULT(ans) + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + LOGICAL(LGT) :: ans + END FUNCTION obj_isInitiated +END INTERFACE END MODULE AbstractMaterialModel_Class diff --git a/src/submodules/AbstractMaterialModel/CMakeLists.txt b/src/submodules/AbstractMaterialModel/CMakeLists.txt new file mode 100644 index 000000000..52b54e25f --- /dev/null +++ b/src/submodules/AbstractMaterialModel/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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}/AbstractMaterialModel_Class@SetMethods.F90 + ${src_path}/AbstractMaterialModel_Class@GetMethods.F90 + ${src_path}/AbstractMaterialModel_Class@IOMethods.F90 + ${src_path}/AbstractMaterialModel_Class@ConstructorMethods.F90) diff --git a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@ConstructorMethods.F90 b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@ConstructorMethods.F90 new file mode 100644 index 000000000..9c981814a --- /dev/null +++ b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@ConstructorMethods.F90 @@ -0,0 +1,53 @@ +! 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(AbstractMaterialModel_Class) ConstructorMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_CheckEssentialParam +CHARACTER(*), PARAMETER :: myName = "obj_CheckEssentialParam" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of'// & + & CHAR_LF//'AbstractSolidMechanicsModel_') +END PROCEDURE obj_CheckEssentialParam + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Initiate +CHARACTER(*), PARAMETER :: myName = "obj_Initiate" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & CHAR_LF//'AbstractSolidMechanicsModel_') +END PROCEDURE obj_Initiate + +!---------------------------------------------------------------------------- +! +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Deallocate +obj%name = "" +obj%isInit = .FALSE. +END PROCEDURE obj_Deallocate + +END SUBMODULE ConstructorMethods diff --git a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 new file mode 100644 index 000000000..9d48bdb24 --- /dev/null +++ b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 @@ -0,0 +1,50 @@ +! 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(AbstractMaterialModel_Class) GetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! GetPrefix +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_GetPrefix +CHARACTER(*), PARAMETER :: myName = "obj_GetPrefix()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +ans = "" +END PROCEDURE obj_GetPrefix + +!---------------------------------------------------------------------------- +! GetName +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_GetName +ans = obj%name%chars() +END PROCEDURE obj_GetName + +!---------------------------------------------------------------------------- +! isInitiated +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_isInitiated +ans = obj%isInit +END PROCEDURE obj_isInitiated + +END SUBMODULE GetMethods diff --git a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@IOMethods.F90 b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@IOMethods.F90 new file mode 100644 index 000000000..4ebc45238 --- /dev/null +++ b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@IOMethods.F90 @@ -0,0 +1,75 @@ +! 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(AbstractMaterialModel_Class) IOMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! Import +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Import +CHARACTER(*), PARAMETER :: myName = "obj_Import" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE obj_Import + +!---------------------------------------------------------------------------- +! Export +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Export +CHARACTER(*), PARAMETER :: myName = "obj_Export" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE obj_Export + +!---------------------------------------------------------------------------- +! Display +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_Display +CHARACTER(*), PARAMETER :: myName = "obj_Display" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by child of '// & + & 'AbstractSolidMechanicsModel_') +END PROCEDURE obj_Display + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_ImportFromToml1 +CHARACTER(*), PARAMETER :: myName = "obj_ImportFromToml1()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This method is under development.') +END PROCEDURE obj_ImportFromToml1 + +!---------------------------------------------------------------------------- +! ImportFromToml +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_ImportFromToml2 +CHARACTER(*), PARAMETER :: myName = "obj_ImportFromToml2()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This method is under development.') +END PROCEDURE obj_ImportFromToml2 + +END SUBMODULE IOMethods diff --git a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 new file mode 100644 index 000000000..cd793c8fb --- /dev/null +++ b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 @@ -0,0 +1,38 @@ +! 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(AbstractMaterialModel_Class) SetMethods +IMPLICIT NONE +CONTAINS + +!---------------------------------------------------------------------------- +! SetIsInitiated +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_SetIsInitiated +obj%isInit = VALUE +END PROCEDURE obj_SetIsInitiated + +!---------------------------------------------------------------------------- +! SetName +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_SetName +obj%name = VALUE +END PROCEDURE obj_SetName + +END SUBMODULE SetMethods diff --git a/src/submodules/CMakeLists.txt b/src/submodules/CMakeLists.txt index ee9146a3f..b822c8944 100644 --- a/src/submodules/CMakeLists.txt +++ b/src/submodules/CMakeLists.txt @@ -260,6 +260,9 @@ include(${CMAKE_CURRENT_LIST_DIR}/PLPlot/CMakeLists.txt) # materials here +# AbstractMaterialModel +include(${CMAKE_CURRENT_LIST_DIR}/AbstractMaterialModel/CMakeLists.txt) + # AbstractSolidMechanicsModel include(${CMAKE_CURRENT_LIST_DIR}/AbstractSolidMechanicsModel/CMakeLists.txt) From 078778a22f6f02cc6e2e1a2c41b683fec3046ec7 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 16:35:03 +0900 Subject: [PATCH 110/117] Updates in AbstractMaterialModel Adding Set and Get api methods. --- .../src/AbstractMaterialModel_Class.F90 | 89 ++++++++++++++++++- ...AbstractMaterialModel_Class@GetMethods.F90 | 21 +++++ ...AbstractMaterialModel_Class@SetMethods.F90 | 20 +++++ 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 index 0cd780713..cd564e56c 100644 --- a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 +++ b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 @@ -68,13 +68,26 @@ MODULE AbstractMaterialModel_Class ! GET: ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => obj_GetPrefix + !! Get the prefix PROCEDURE, PUBLIC, PASS(obj) :: GetName => obj_GetName + !! Returns the name PROCEDURE, PUBLIC, PASS(obj) :: isInitiated => obj_isInitiated + !! Returns the init status + PROCEDURE, PUBLIC, PASS(obj) :: GetDataSize => obj_GetDataSize + !! Get size of data + PROCEDURE, PUBLIC, PASS(obj) :: GetData => obj_GetData + !! Get the data ! SET: ! @SetMethods PROCEDURE, PUBLIC, PASS(obj) :: SetIsInitiated => obj_SetIsInitiated + !! Set the status of AbstractMaterialModel PROCEDURE, PUBLIC, PASS(obj) :: SetName => obj_SetName + !! Set name of AbstractMaterialModel_ + PROCEDURE, PUBLIC, PASS(obj) :: SetData => obj_SetData + !! Set data + PROCEDURE, PUBLIC, PASS(obj) :: UpdateData => obj_UpdateData + !! Get updated data END TYPE AbstractMaterialModel_ !---------------------------------------------------------------------------- @@ -223,9 +236,13 @@ END SUBROUTINE obj_SetIsInitiated END INTERFACE !---------------------------------------------------------------------------- -! SetName +! SetName@SetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Set the name of material model + INTERFACE MODULE SUBROUTINE obj_SetName(obj, VALUE) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj @@ -234,7 +251,37 @@ END SUBROUTINE obj_SetName END INTERFACE !---------------------------------------------------------------------------- -! GetPrefix +! SetData@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Set data + +INTERFACE + MODULE SUBROUTINE obj_SetData(obj, DATA) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + REAL(DFP), INTENT(IN) :: DATA(:) + END SUBROUTINE obj_SetData +END INTERFACE + +!---------------------------------------------------------------------------- +! UpdateData@SetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Update data + +INTERFACE + MODULE SUBROUTINE obj_UpdateData(obj, DATA) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + REAL(DFP), INTENT(INOUT) :: DATA(:) + END SUBROUTINE obj_UpdateData +END INTERFACE + +!---------------------------------------------------------------------------- +! GetPrefix@GetMethods !---------------------------------------------------------------------------- !> author: Vikas Sharma, Ph. D. @@ -249,7 +296,7 @@ END FUNCTION obj_GetPrefix END INTERFACE !---------------------------------------------------------------------------- -! GetName +! GetName@GetMethods !---------------------------------------------------------------------------- INTERFACE @@ -260,9 +307,13 @@ END FUNCTION obj_GetName END INTERFACE !---------------------------------------------------------------------------- -! isInitiated +! isInitiated@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Returns the init status of obj + INTERFACE MODULE FUNCTION obj_isInitiated(obj) RESULT(ans) CLASS(AbstractMaterialModel_), INTENT(IN) :: obj @@ -270,4 +321,34 @@ MODULE FUNCTION obj_isInitiated(obj) RESULT(ans) END FUNCTION obj_isInitiated END INTERFACE +!---------------------------------------------------------------------------- +! GetDataSize@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get the size of data needed by obj + +INTERFACE + MODULE FUNCTION obj_GetDataSize(obj) RESULT(ans) + CLASS(AbstractMaterialModel_), INTENT(IN) :: obj + INTEGER(I4B) :: ans + END FUNCTION obj_GetDataSize +END INTERFACE + +!---------------------------------------------------------------------------- +! GetData@GetMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get the data from the model + +INTERFACE + MODULE SUBROUTINE obj_GetData(obj, DATA) + CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj + REAL(DFP), INTENT(INOUT) :: DATA(:) + END SUBROUTINE obj_GetData +END INTERFACE + END MODULE AbstractMaterialModel_Class diff --git a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 index 9d48bdb24..3a025e4b9 100644 --- a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 +++ b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@GetMethods.F90 @@ -47,4 +47,25 @@ ans = obj%isInit END PROCEDURE obj_isInitiated +!---------------------------------------------------------------------------- +! GetDataSize +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_GetDataSize +CHARACTER(*), PARAMETER :: myName = "obj_GetDataSize()" +ans = 0 +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine must be implemented by subclass.') +END PROCEDURE obj_GetDataSize + +!---------------------------------------------------------------------------- +! GetData +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_GetData +CHARACTER(*), PARAMETER :: myName = "obj_GetData()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine must be implemented by subclass.') +END PROCEDURE obj_GetData + END SUBMODULE GetMethods diff --git a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 index cd793c8fb..f0bdf9741 100644 --- a/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 +++ b/src/submodules/AbstractMaterialModel/src/AbstractMaterialModel_Class@SetMethods.F90 @@ -35,4 +35,24 @@ obj%name = VALUE END PROCEDURE obj_SetName +!---------------------------------------------------------------------------- +! SetData +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_SetData +CHARACTER(*), PARAMETER :: myName = "obj_SetData()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by subclass.') +END PROCEDURE obj_SetData + +!---------------------------------------------------------------------------- +! UpdateData +!---------------------------------------------------------------------------- + +MODULE PROCEDURE obj_UpdateData +CHARACTER(*), PARAMETER :: myName = "obj_UpdateData()" +CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[WIP ERROR] :: This routine should be implemented by subclass.') +END PROCEDURE obj_UpdateData + END SUBMODULE SetMethods From 4c0bac8a96cb91cbd01d42090d2e99c540742391 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 18:11:53 +0900 Subject: [PATCH 111/117] Update AbstractMaterialModel_Class.F90 Minor formatting. --- .../src/AbstractMaterialModel_Class.F90 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 index cd564e56c..d201db5a0 100644 --- a/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 +++ b/src/modules/AbstractMaterialModel/src/AbstractMaterialModel_Class.F90 @@ -228,6 +228,10 @@ END SUBROUTINE obj_ImportFromToml2 ! SetIsInitiated@SetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Set initiate status + INTERFACE MODULE SUBROUTINE obj_SetIsInitiated(obj, VALUE) CLASS(AbstractMaterialModel_), INTENT(INOUT) :: obj @@ -299,6 +303,10 @@ END FUNCTION obj_GetPrefix ! GetName@GetMethods !---------------------------------------------------------------------------- +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Get the name of model + INTERFACE MODULE FUNCTION obj_GetName(obj) RESULT(ans) CLASS(AbstractMaterialModel_), INTENT(IN) :: obj From c84a4e6f226affa0d74c786c04740525d1cd60f8 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 18:14:54 +0900 Subject: [PATCH 112/117] Update AbstractSolidMechanicsModel_Class.F90 Removing elasticityType parameters. --- .../src/AbstractSolidMechanicsModel_Class.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 b/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 index fe6ef94d7..62e7879bb 100644 --- a/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 +++ b/src/modules/AbstractSolidMechanicsModel/src/AbstractSolidMechanicsModel_Class.F90 @@ -35,11 +35,6 @@ MODULE AbstractSolidMechanicsModel_Class PUBLIC :: AbstractSolidMechanicsModel_ PUBLIC :: AbstractSolidMechanicsModelDeallocate -INTEGER(I4B), PARAMETER, PUBLIC :: IsoLinearElasticModel = 1 -INTEGER(I4B), PARAMETER, PUBLIC :: AnisoLinearElasticModel = 2 -INTEGER(I4B), PARAMETER, PUBLIC :: OrthoLinearElasticModel = 3 -INTEGER(I4B), PARAMETER, PUBLIC :: TransLinearElasticModel = 4 - !---------------------------------------------------------------------------- ! AbstractSolidMechanicsModel_ !---------------------------------------------------------------------------- From 810609952b9acbeec1fbb02c73ba2d23786d4e49 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 18:35:45 +0900 Subject: [PATCH 113/117] Updates in STScalarField_Class Fixes issue #225 --- .../STScalarField/src/STScalarField_Class.F90 | 6 +- .../src/STScalarField_Class@DBCMethods.F90 | 132 ++++++++---------- 2 files changed, 62 insertions(+), 76 deletions(-) diff --git a/src/modules/STScalarField/src/STScalarField_Class.F90 b/src/modules/STScalarField/src/STScalarField_Class.F90 index 7b41d2e01..aa043024f 100644 --- a/src/modules/STScalarField/src/STScalarField_Class.F90 +++ b/src/modules/STScalarField/src/STScalarField_Class.F90 @@ -1031,9 +1031,10 @@ END FUNCTION stsField_GetPrefix ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE stsField_ApplyDirichletBC1(obj, dbc) + MODULE SUBROUTINE stsField_ApplyDirichletBC1(obj, dbc, times) CLASS(STScalarField_), INTENT(INOUT) :: obj CLASS(DirichletBC_), INTENT(IN) :: dbc + REAL(DFP), OPTIONAL, INTENT(IN) :: times(:) END SUBROUTINE stsField_ApplyDirichletBC1 END INTERFACE @@ -1046,9 +1047,10 @@ END SUBROUTINE stsField_ApplyDirichletBC1 ! summary: Apply Dirichlet boundary condition INTERFACE - MODULE SUBROUTINE stsField_ApplyDirichletBC2(obj, dbc) + MODULE SUBROUTINE stsField_ApplyDirichletBC2(obj, dbc, times) CLASS(STScalarField_), INTENT(INOUT) :: obj CLASS(DirichletBCPointer_), INTENT(IN) :: dbc(:) + REAL(DFP), OPTIONAL, INTENT(IN) :: times(:) END SUBROUTINE stsField_ApplyDirichletBC2 END INTERFACE diff --git a/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 index 9b3b8cf9c..d44d7a9b1 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 @@ -25,42 +25,33 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE stsField_applyDirichletBC1 - CHARACTER( LEN = * ), PARAMETER :: myName = "stsField_applyDirichletBC1" - REAL( DFP ), ALLOCATABLE :: nodalvalue(:,:) - INTEGER( I4B ), ALLOCATABLE :: nodenum( : ) - INTEGER( I4B ) :: idof - !! - !! main - !! - CALL dbc%get( nodalvalue=nodalvalue, nodenum=nodenum ) - !! - IF( size( nodalvalue, 2 ) .EQ. 1 ) THEN - !! - DO idof = 1, obj%timecompo - CALL obj%Set( & - & globalNode=nodenum, & - & value=nodalvalue(:,1), & - & timecompo=idof ) - END DO - !! - ELSE - !! - !! check - !! - IF( SIZE( nodalvalue, 2 ) .NE. obj%timeCompo ) & - & CALL e%raiseError(modName//'::'//myName// " - "// & - & 'SIZE( nodalvalue, 2 ) .NE. obj%timeCompo') - !! - CALL obj%Set( & - & globalNode=nodenum, & - & value=nodalvalue ) - !! +CHARACTER(*), PARAMETER :: myName = "stsField_applyDirichletBC1()" +REAL(DFP), ALLOCATABLE :: nodalvalue(:, :) +INTEGER(I4B), ALLOCATABLE :: nodenum(:) +INTEGER(I4B) :: idof, aint + +CALL dbc%get(nodalvalue=nodalvalue, nodenum=nodenum, times=times) + +IF (SIZE(nodalvalue, 2) .EQ. 1) THEN + DO idof = 1, obj%timecompo + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, 1), & + & timecompo=idof) + END DO + +ELSE + aint = SIZE(nodalvalue, 2) + IF (SIZE(nodalvalue, 2) .NE. obj%timeCompo) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INERNAL ERROR] :: SIZE( nodalvalue, 2 ) is '// & + & tostring(aint)//' which is not equal to obj%timeCompo '// & + & ' which is '//tostring(obj%timeCompo)) END IF - !! - !! - IF( ALLOCATED( nodalvalue ) ) DEALLOCATE( nodalvalue ) - IF( ALLOCATED( nodenum ) ) DEALLOCATE( nodenum ) - !! + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue) + +END IF + +IF (ALLOCATED(nodalvalue)) DEALLOCATE (nodalvalue) +IF (ALLOCATED(nodenum)) DEALLOCATE (nodenum) END PROCEDURE stsField_applyDirichletBC1 !---------------------------------------------------------------------------- @@ -68,49 +59,42 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE stsField_applyDirichletBC2 - CHARACTER( LEN = * ), PARAMETER :: myName = "stsField_applyDirichletBC2" - REAL( DFP ), ALLOCATABLE :: nodalvalue(:,:) - INTEGER( I4B ), ALLOCATABLE :: nodenum( : ) - INTEGER( I4B ) :: idof, ii - !! - !! main - !! - DO ii = 1, SIZE( dbc ) - !! - CALL dbc(ii)%ptr%get( nodalvalue=nodalvalue, nodenum=nodenum ) - !! - IF( SIZE( nodalvalue, 2 ) .EQ. 1 ) THEN - !! - DO idof = 1, obj%timecompo - CALL obj%Set( & - & globalNode=nodenum, & - & value=nodalvalue(:,1), & - & timecompo=idof ) - END DO - !! - ELSE - !! - !! check - !! - IF( SIZE( nodalvalue, 2 ) .NE. obj%timeCompo ) & - & CALL e%raiseError(modName//'::'//myName// " - "// & - & 'SIZE( nodalvalue, 2 ) .NE. obj%timeCompo') - !! - CALL obj%Set( & - & globalNode=nodenum, & - & value=nodalvalue ) - !! +CHARACTER(*), PARAMETER :: myName = "stsField_applyDirichletBC2" +REAL(DFP), ALLOCATABLE :: nodalvalue(:, :) +INTEGER(I4B), ALLOCATABLE :: nodenum(:) +INTEGER(I4B) :: idof, ii, aint + +DO ii = 1, SIZE(dbc) + CALL dbc(ii)%ptr%get(nodalvalue=nodalvalue, nodenum=nodenum, & + & times=times) + + IF (SIZE(nodalvalue, 2) .EQ. 1) THEN + DO idof = 1, obj%timecompo + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, 1), & + & timecompo=idof) + END DO + + ELSE + + aint = SIZE(nodalvalue, 2) + + IF (SIZE(nodalvalue, 2) .NE. obj%timeCompo) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INERNAL ERROR] :: SIZE( nodalvalue, 2 ) is '// & + & tostring(aint)//' which is not equal to obj%timeCompo '// & + & ' which is '//tostring(obj%timeCompo)) END IF - !! - END DO - !! - IF( ALLOCATED( nodalvalue ) ) DEALLOCATE( nodalvalue ) - IF( ALLOCATED( nodenum ) ) DEALLOCATE( nodenum ) - !! + + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue) + END IF +END DO + +IF (ALLOCATED(nodalvalue)) DEALLOCATE (nodalvalue) +IF (ALLOCATED(nodenum)) DEALLOCATE (nodenum) END PROCEDURE stsField_applyDirichletBC2 !---------------------------------------------------------------------------- ! !---------------------------------------------------------------------------- -END SUBMODULE DBCMethods \ No newline at end of file +END SUBMODULE DBCMethods From 2e8a948c5a4f3c9446556726ebee8f133d1bef6c Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 18:37:31 +0900 Subject: [PATCH 114/117] Updates in LinearElasticModel Working towards new api for material model. This is still work in progress. --- .../src/LinearElasticModel_Class.F90 | 82 ++++++++++++-- ...rElasticModel_Class@ConstructorMethods.F90 | 102 ++++++++++++------ .../LinearElasticModel_Class@IOMethods.F90 | 20 ++-- 3 files changed, 149 insertions(+), 55 deletions(-) diff --git a/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 b/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 index 4cba29723..deffd3eba 100644 --- a/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 +++ b/src/modules/LinearElasticModel/src/LinearElasticModel_Class.F90 @@ -38,6 +38,31 @@ MODULE LinearElasticModel_Class PUBLIC :: Get_PlaneStress_C_InvC PUBLIC :: Get_PlaneStrain_C_InvC PUBLIC :: Get_3D_C_InvC +PUBLIC :: TypeElasticity +PUBLIC :: ElasticityType_char +PUBLIC :: ElasticityType_tonumber + +INTEGER(I4B), PARAMETER, PUBLIC :: IsoLinearElasticModel = 1 +INTEGER(I4B), PARAMETER, PUBLIC :: AnisoLinearElasticModel = 2 +INTEGER(I4B), PARAMETER, PUBLIC :: OrthoLinearElasticModel = 3 +INTEGER(I4B), PARAMETER, PUBLIC :: TransLinearElasticModel = 4 + +!---------------------------------------------------------------------------- +! ElasticityType_ +!---------------------------------------------------------------------------- + +TYPE :: ElasticityType_ + INTEGER(I4B) :: Isotropic = IsoLinearElasticModel + INTEGER(I4B) :: Anisotropic = AnisoLinearElasticModel + INTEGER(I4B) :: Orthotropic = OrthoLinearElasticModel + INTEGER(I4B) :: TransIsotropic = TransLinearElasticModel + CHARACTER(3) :: Isotropic_char = "ISO" + CHARACTER(5) :: Anisotropic_char = "ANISO" + CHARACTER(5) :: Orthotropic_char = "ORTHO" + CHARACTER(5) :: TransIsotropic_chars = "TRANS" +END TYPE ElasticityType_ + +TYPE(ElasticityType_), PARAMETER :: TypeElasticity = ElasticityType_() !---------------------------------------------------------------------------- ! LinearElasticModel_ @@ -57,27 +82,36 @@ MODULE LinearElasticModel_Class REAL(DFP) :: C(6, 6) = 0.0_DFP REAL(DFP) :: invC(6, 6) = 0.0_DFP REAL(DFP) :: stiffnessPower = 0.0_DFP + CONTAINS PRIVATE + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: CheckEssentialParam => & & lem_CheckEssentialParam PROCEDURE, PUBLIC, PASS(obj) :: Initiate => lem_Initiate PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => lem_Deallocate FINAL :: lem_FINAL + + ! IO: + ! @IOMethods PROCEDURE, PUBLIC, PASS(obj) :: IMPORT => lem_Import PROCEDURE, PUBLIC, PASS(obj) :: Export => lem_Export PROCEDURE, PUBLIC, PASS(obj) :: Display => lem_Display + + ! GET: + ! @GetMethods PROCEDURE, PUBLIC, PASS(obj) :: GetElasticParam => lem_GetElasticParam PROCEDURE, PUBLIC, PASS(obj) :: GetC => lem_GetC PROCEDURE, PUBLIC, PASS(obj) :: GetInvC => lem_GetInvC - PROCEDURE, PUBLIC, PASS(obj) :: GetElasticityType => & - & lem_GetElasticityType - PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => & - & lem_GetPrefix - PROCEDURE, PUBLIC, PASS(obj) :: GetParam => & - & lem_GetParam - PROCEDURE, PUBLIC, PASS(obj) :: SetParam => & - & lem_SetParam + PROCEDURE, PUBLIC, PASS(obj) :: GetElasticityType => lem_GetElasticityType + PROCEDURE, PUBLIC, PASS(obj) :: GetPrefix => lem_GetPrefix + PROCEDURE, PUBLIC, PASS(obj) :: GetParam => lem_GetParam + + ! SET: + ! @SetMethods + PROCEDURE, PUBLIC, PASS(obj) :: SetParam => lem_SetParam END TYPE LinearElasticModel_ TYPE(LinearElasticModel_), PARAMETER :: TypeLinearElasticModel = & @@ -91,13 +125,43 @@ MODULE LinearElasticModel_Class CLASS(LinearElasticModel_), POINTER :: ptr => NULL() END TYPE LinearElasticModelPointer_ +!---------------------------------------------------------------------------- +! ElasticityType_tonumber@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Returns the elasticity number + +INTERFACE + MODULE FUNCTION ElasticityType_tonumber(name) RESULT(ans) + CHARACTER(*), INTENT(IN) :: name + INTEGER(I4B) :: ans + END FUNCTION ElasticityType_tonumber +END INTERFACE + +!---------------------------------------------------------------------------- +! ElasticityType_tonumber@ConstructorMethods +!---------------------------------------------------------------------------- + +!> author: Vikas Sharma, Ph. D. +! date: 2023-11-30 +! summary: Returns the elasticity number + +INTERFACE + MODULE FUNCTION ElasticityType_char(num) RESULT(ans) + INTEGER(I4B), INTENT(IN) :: num + CHARACTER(:), ALLOCATABLE :: ans + END FUNCTION ElasticityType_char +END INTERFACE + !---------------------------------------------------------------------------- ! SetLinearElasticModelParam@ConstructorMethods !---------------------------------------------------------------------------- !> authors: Vikas Sharma, Ph. D. ! date: 27 Aug 2021 -! summary: Check the essential parameter +! summary: Set the essential parameter INTERFACE MODULE SUBROUTINE SetLinearElasticModelParam(param, elasticityType, & diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 index a9470c3f7..ebf6353dd 100644 --- a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@ConstructorMethods.F90 @@ -16,17 +16,67 @@ ! SUBMODULE(LinearElasticModel_Class) ConstructorMethods -USE BaseMethod, ONLY: Input +USE BaseMethod, ONLY: Input, UpperCase, ToString USE FPL_Method IMPLICIT NONE CONTAINS +!---------------------------------------------------------------------------- +! ElasticityType_tonumber +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ElasticityType_tonumber +CHARACTER(*), PARAMETER :: myName = "ElasticityType_tonumber" +TYPE(String) :: name0 + +name0 = UpperCase(name) +SELECT CASE (name0%chars()) +CASE ("ISO") + ans = TypeElasticity%Isotropic +CASE ("ANISO") + ans = TypeElasticity%Anisotropic +CASE ("ORTHO") + ans = TypeElasticity%Orthotropic +CASE ("TRANS") + ans = TypeElasticity%TransIsotropic +CASE default + CALL e%RaiseError(modName//'::'//myName//' - '// & + & 'NO CASE FOUND for name = '//name0) + RETURN +END SELECT + +name0 = "" +END PROCEDURE ElasticityType_tonumber + +!---------------------------------------------------------------------------- +! ElasticityType_char +!---------------------------------------------------------------------------- + +MODULE PROCEDURE ElasticityType_char +CHARACTER(*), PARAMETER :: myName = "ElasticityType_char" +SELECT CASE (num) +CASE (IsoLinearElasticModel) + ans = TypeElasticity%Isotropic_char +CASE (AnisoLinearElasticModel) + ans = TypeElasticity%Anisotropic_char +CASE (OrthoLinearElasticModel) + ans = TypeElasticity%Orthotropic_char +CASE (TransLinearElasticModel) + ans = TypeElasticity%TransIsotropic_chars +CASE default + CALL e%RaiseError(modName//'::'//myName//' - '// & + & '[INTERNAL ERROR] No case found for elasticityType = '// & + & tostring(num)) + RETURN +END SELECT +END PROCEDURE ElasticityType_char + !---------------------------------------------------------------------------- ! setLinearElasticModelParam !---------------------------------------------------------------------------- MODULE PROCEDURE SetLinearElasticModelParam -CHARACTER(*), PARAMETER :: myName = "SetLinearElasticModelParam" +CHARACTER(*), PARAMETER :: myName = "SetLinearElasticModelParam()" INTEGER(I4B) :: ierr REAL(DFP) :: lam, EE, nu, G TYPE(String) :: astr @@ -35,27 +85,18 @@ CALL Set(obj=param, datatype="char", prefix=myprefix, key="name", & & VALUE=myprefix) -SELECT CASE (elasticityType) -CASE (IsoLinearElasticModel) - astr = "ISO" -CASE (AnisoLinearElasticModel) - astr = "ANISO" -CASE (OrthoLinearElasticModel) - astr = "ORTHO" -CASE (TransLinearElasticModel) - astr = "TRANS" -END SELECT +astr = ElasticityType_char(elasticityType) CALL Set(obj=param, datatype="char", prefix=myprefix, & & key="elasticityType", VALUE=astr%chars()) CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStrain", & - & VALUE=input(option=isPlaneStrain, default=.FALSE.)) + & VALUE=INPUT(option=isPlaneStrain, default=.FALSE.)) CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStress", & & VALUE=input(option=isPlaneStress, default=.FALSE.)) -isIsotropic = elasticityType .EQ. IsoLinearElasticModel +isIsotropic = elasticityType .EQ. TypeElasticity%Isotropic IF (isIsotropic) THEN CALL GetElasticParam(lam=lam, G=G, EE=EE, nu=nu, & @@ -91,8 +132,7 @@ ierr = param%Set(key=myprefix//"/invC", VALUE=invC) END IF -CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, & - & key="stiffnessPower", & +CALL Set(obj=param, datatype=1.0_DFP, prefix=myprefix, key="stiffnessPower",& & VALUE=INPUT(option=stiffnessPower, default=0.0_DFP)) END PROCEDURE SetLinearElasticModelParam @@ -102,7 +142,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE lem_CheckEssentialParam -CHARACTER(*), PARAMETER :: myName = "lem_CheckEssentialParam" +CHARACTER(*), PARAMETER :: myName = "lem_CheckEssentialParam()" CHARACTER(15) :: charVar INTEGER(I4B) :: ierr, cc INTEGER(I4B), ALLOCATABLE :: shapeOfC(:) @@ -138,7 +178,7 @@ ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) cc = 0 -IF (TRIM(charVar) .EQ. "ISO") THEN +IF (TRIM(charVar) .EQ. TypeElasticity%Isotropic_char) THEN IF (.NOT. param%IsPresent(key=myprefix//"/lambda")) & & CALL e%RaiseError(modName//'::'//myName//" - "// & & myprefix//'/lambda should be present in param') @@ -185,6 +225,8 @@ END IF +IF (ALLOCATED(shapeOfC)) DEALLOCATE (shapeOfC) + END PROCEDURE lem_CheckEssentialParam !---------------------------------------------------------------------------- @@ -192,7 +234,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE lem_Initiate -CHARACTER(*), PARAMETER :: myName = "lem_Initiate" +CHARACTER(*), PARAMETER :: myName = "lem_Initiate()" CHARACTER(15) :: charVar INTEGER(I4B) :: ierr LOGICAL(LGT) :: isPlaneStress @@ -203,24 +245,20 @@ & '[START] Initiate()') #endif +CALL obj%DEALLOCATE() + CALL obj%CheckEssentialParam(param) CALL obj%SetIsInitiated(.TRUE.) CALL obj%SetName(myprefix) + ierr = param%get(key=myprefix//"/isPlaneStress", VALUE=isPlaneStress) CALL obj%SetPlaneStress(isPlaneStress) + ierr = param%get(key=myprefix//"/isPlaneStrain", VALUE=isPlaneStrain) CALL obj%SetPlaneStrain(isPlaneStrain) -ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) -IF (TRIM(charVar) .EQ. "ISO") THEN - obj%elasticityType = IsoLinearElasticModel -ELSE IF (TRIM(charVar) .EQ. "ANISO") THEN - obj%elasticityType = AnisoLinearElasticModel -ELSE IF (TRIM(charVar) .EQ. "ORTHO") THEN - obj%elasticityType = OrthoLinearElasticModel -ELSE IF (TRIM(charVar) .EQ. "TRANS") THEN - obj%elasticityType = TransLinearElasticModel -END IF +ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) +obj%elasticityType = elasticityType_tonumber(charVar) IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN ierr = param%get(key=myprefix//"/lambda", VALUE=obj%lambda) @@ -228,13 +266,13 @@ ierr = param%get(key=myprefix//"/youngsModulus", VALUE=obj%E) ierr = param%get(key=myprefix//"/poissonRatio", VALUE=obj%nu) IF (isPlaneStress) THEN - CALL get_PlaneStress_C_InvC(C=obj%C, invC=obj%invC, & + CALL Get_PlaneStress_C_InvC(C=obj%C, invC=obj%invC, & & youngsModulus=obj%E, nu=obj%nu) ELSEIF (isPlaneStrain) THEN - CALL get_PlaneStrain_C_InvC(C=obj%C, invC=obj%invC, & + CALL Get_PlaneStrain_C_InvC(C=obj%C, invC=obj%invC, & & youngsModulus=obj%E, nu=obj%nu) ELSE - CALL get_3D_C_InvC(C=obj%C, invC=obj%invC, & + CALL Get_3D_C_InvC(C=obj%C, invC=obj%invC, & & youngsModulus=obj%E, nu=obj%nu) END IF ELSE diff --git a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 index d797e95cf..b4eef1f06 100644 --- a/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 +++ b/src/submodules/LinearElasticModel/src/LinearElasticModel_Class@IOMethods.F90 @@ -32,7 +32,7 @@ CHARACTER(*), PARAMETER :: myName = "lem_Import" INTEGER(I4B) :: elasticityType TYPE(String) :: dsetname, strval -LOGICAL(LGT) :: isPlaneStrain, isPlaneStress +LOGICAL(LGT) :: isPlaneStrain, isPlaneStress, isIsotropic REAL(DFP) :: poissonRatio, youngsModulus, shearModulus, lambda, stiffnessPower REAL(DFP), ALLOCATABLE :: C(:, :), invC(:, :) TYPE(ParameterList_) :: param @@ -58,7 +58,6 @@ END IF ! READ name - dsetname = TRIM(group)//"/name" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%raiseError(modName//'::'//myName//" - "// & @@ -73,17 +72,7 @@ & '[CONFIG ERROR] :: The dataset elasticityType should be present') END IF CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) - -SELECT CASE (TRIM(strval%chars())) -CASE ("ISO") - elasticityType = IsoLinearElasticModel -CASE ("ANISO") - elasticityType = AnisoLinearElasticModel -CASE ("ORTHO") - elasticityType = OrthoLinearElasticModel -CASE ("TRANS") - elasticityType = TransLinearElasticModel -END SELECT +elasticityType = ElasticityType_tonumber(strval%chars()) ! READ isPlaneStrain dsetname = TRIM(group)//"/isPlaneStrain" @@ -101,7 +90,9 @@ isPlaneStress = .FALSE. END IF -IF (elasticityType .EQ. IsoLinearElasticModel) THEN +isIsotropic = elasticityType .EQ. TypeElasticity%Isotropic + +IF (isIsotropic) THEN dsetname = TRIM(group)//"/poissonRatio" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%raiseError(modName//'::'//myName//" - "// & @@ -109,6 +100,7 @@ ELSE CALL hdf5%READ(dsetname=dsetname%chars(), vals=poissonRatio) END IF + dsetname = TRIM(group)//"/youngsModulus" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%raiseError(modName//'::'//myName//" - "// & From 4e975ed82c704c2251ea1ff17f33b0a81a164b33 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 18:38:58 +0900 Subject: [PATCH 115/117] Updates in Poroelastic material models Working towards new api for material models --- .../src/AbstractPoroMechanicsModel_Class.F90 | 5 -- ...oElasticModel_Class@ConstructorMethods.F90 | 37 ++++++--------- ...LinearPoroElasticModel_Class@IOMethods.F90 | 46 +++++++------------ 3 files changed, 31 insertions(+), 57 deletions(-) diff --git a/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 b/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 index 2e2a1f223..bab56ed16 100644 --- a/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 +++ b/src/modules/AbstractPoroMechanicsModel/src/AbstractPoroMechanicsModel_Class.F90 @@ -24,11 +24,6 @@ MODULE AbstractPoroMechanicsModel_Class IMPLICIT NONE PRIVATE CHARACTER(*), PARAMETER :: modName = "AbstractPoroMechanicsModel_Class" - -PUBLIC :: IsoLinearElasticModel -PUBLIC :: AnisoLinearElasticModel -PUBLIC :: OrthoLinearElasticModel -PUBLIC :: TransLinearElasticModel PUBLIC :: AbstractPoroMechanicsModel_ !---------------------------------------------------------------------------- diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 index 9b817848d..5aa02e1d4 100644 --- a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@ConstructorMethods.F90 @@ -17,8 +17,16 @@ SUBMODULE(LinearPoroElasticModel_Class) ConstructorMethods USE BaseMethod, ONLY: Input -USE easifemMaterials USE FPL_Method +USE AbstractSolidMechanicsModel_Class, ONLY: & + & AbstractSolidMechanicsModelDeallocate +USE LinearElasticModel_Class, ONLY: ElasticityType_char, & + & ElasticityType_tonumber, & + & TypeElasticity, & + & Get_PlaneStress_C_InvC, & + & Get_PlaneStrain_C_InvC, & + & Get_3D_C_InvC, & + & GetElasticParam IMPLICIT NONE CONTAINS @@ -36,16 +44,7 @@ CALL Set(obj=param, datatype="char", prefix=myprefix, key="name", & & VALUE=myprefix) -SELECT CASE (elasticityType) -CASE (IsoLinearElasticModel) - astr = "ISO" -CASE (AnisoLinearElasticModel) - astr = "ANISO" -CASE (OrthoLinearElasticModel) - astr = "ORTHO" -CASE (TransLinearElasticModel) - astr = "TRANS" -END SELECT +astr = ElasticityType_char(elasticityType) CALL Set(obj=param, datatype="char", prefix=myprefix, & & key="elasticityType", VALUE=astr%chars()) @@ -56,7 +55,7 @@ CALL Set(obj=param, datatype=.TRUE., prefix=myprefix, key="isPlaneStress", & & VALUE=input(option=isPlaneStress, default=.FALSE.)) -isIsotropic = elasticityType .EQ. IsoLinearElasticModel +isIsotropic = elasticityType .EQ. TypeElasticity%Isotropic IF (isIsotropic) THEN CALL GetElasticParam(lam=lam, G=G, EE=EE, nu=nu, & @@ -193,6 +192,7 @@ INTEGER(I4B) :: ierr LOGICAL(LGT) :: isPlaneStrain LOGICAL(LGT) :: isPlaneStress +LOGICAL(LGT) :: isIsotropic #ifdef DEBUG_VER CALL e%RaiseInformation(modName//'::'//myName//' - '// & @@ -208,17 +208,10 @@ CALL obj%SetPlaneStrain(isPlaneStrain) ierr = param%get(key=myprefix//"/elasticityType", VALUE=charVar) -IF (TRIM(charVar) .EQ. "ISO") THEN - obj%elasticityType = IsoLinearElasticModel -ELSE IF (TRIM(charVar) .EQ. "ANISO") THEN - obj%elasticityType = AnIsoLinearElasticModel -ELSE IF (TRIM(charVar) .EQ. "ORTHO") THEN - obj%elasticityType = OrthoLinearElasticModel -ELSE IF (TRIM(charVar) .EQ. "TRANS") THEN - obj%elasticityType = TransLinearElasticModel -END IF +obj%elasticityType = ElasticityType_tonumber(charVar) -IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN +isIsotropic = obj%elasticityType .EQ. TypeElasticity%Isotropic +IF (isIsotropic) THEN ierr = param%get(key=myprefix//"/lambda", VALUE=obj%lambda) ierr = param%get(key=myprefix//"/shearModulus", VALUE=obj%G) ierr = param%get(key=myprefix//"/youngsModulus", VALUE=obj%E) diff --git a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 index 83f4f729a..f256bebfd 100644 --- a/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 +++ b/src/submodules/LinearPoroElasticModel/src/LinearPoroElasticModel_Class@IOMethods.F90 @@ -21,6 +21,9 @@ SUBMODULE(LinearPoroElasticModel_Class) IOMethods USE BaseMethod +USE LinearElasticModel_Class, ONLY: TypeElasticity, & +& ElasticityType_tonumber, & +& ElasticityType_char IMPLICIT NONE CONTAINS @@ -32,7 +35,7 @@ CHARACTER(*), PARAMETER :: myName = "lpem_Import" INTEGER(I4B) :: elasticityType TYPE(String) :: dsetname, strval -LOGICAL(LGT) :: isPlaneStrain, isPlaneStress +LOGICAL(LGT) :: isPlaneStrain, isPlaneStress, isIsotropic REAL(DFP) :: PoissonRatio, YoungsModulus, ShearModulus, lambda REAL(DFP), ALLOCATABLE :: C(:, :), invC(:, :) TYPE(ParameterList_) :: param @@ -75,16 +78,7 @@ END IF CALL hdf5%READ(dsetname=dsetname%chars(), vals=strval) -SELECT CASE (TRIM(strval%chars())) -CASE ("ISO") - elasticityType = IsoLinearElasticModel -CASE ("ANISO") - elasticityType = AnisoLinearElasticModel -CASE ("ORTHO") - elasticityType = OrthoLinearElasticModel -CASE ("TRANS") - elasticityType = TransLinearElasticModel -END SELECT +elasticityType = ElasticityType_tonumber(strval%chars()) !> READ isPlaneStrain dsetname = TRIM(group)//"/isPlaneStrain" @@ -102,7 +96,8 @@ isPlaneStress = .FALSE. END IF -IF (elasticityType .EQ. IsoLinearElasticModel) THEN +isIsotropic = elasticityType .EQ. TypeElasticity%Isotropic +IF (isIsotropic) THEN dsetname = TRIM(group)//"/PoissonRatio" IF (.NOT. hdf5%pathExists(dsetname%chars())) THEN CALL e%RaiseError(modName//'::'//myName//" - "// & @@ -205,16 +200,7 @@ !> WRITE elasticityType dsetname = TRIM(group)//"/elasticityType" -SELECT CASE (obj%elasticityType) -CASE (IsoLinearElasticModel) - strval = "ISO" -CASE (AnisoLinearElasticModel) - strval = "ANISO" -CASE (OrthoLinearElasticModel) - strval = "ORTHO" -CASE (TransLinearElasticModel) - strval = "TRANS" -END SELECT +strval = ElasticityType_char(obj%elasticityType) CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=strval) !> WRITE isPlaneStrain @@ -226,7 +212,7 @@ CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%isPlaneStress()) !> C and invC -IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN +IF (obj%elasticityType .EQ. TypeElasticity%Isotropic) THEN dsetname = TRIM(group)//"/PoissonRatio" CALL hdf5%WRITE(dsetname=dsetname%chars(), vals=obj%nu) dsetname = TRIM(group)//"/YoungsModulus" @@ -257,8 +243,8 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE lpem_Display - LOGICAL( LGT ) :: isPlaneStrain - LOGICAL( LGT ) :: isPlaneStress +LOGICAL(LGT) :: isPlaneStrain +LOGICAL(LGT) :: isPlaneStress CALL Display(TRIM(msg), unitNo=unitNo) CALL Display(obj%isInitiated(), "isInitiated: ", unitNo=unitNo) @@ -267,13 +253,13 @@ END IF CALL Display("name: "//myPrefix, unitNo=unitNo) -IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN +IF (obj%elasticityType .EQ. TypeElasticity%Isotropic) THEN CALL Display("elasticityType: IsoLinearElasticModel", unitNo=unitNo) -ELSE IF (obj%elasticityType .EQ. AnisoLinearElasticModel) THEN +ELSE IF (obj%elasticityType .EQ. TypeElasticity%Anisotropic) THEN CALL Display("elasticityType: AnisoLinearElasticModel", unitNo=unitNo) -ELSE IF (obj%elasticityType .EQ. OrthoLinearElasticModel) THEN +ELSE IF (obj%elasticityType .EQ. TypeElasticity%Orthotropic) THEN CALL Display("elasticityType: OrthoLinearElasticModel", unitNo=unitNo) -ELSE IF (obj%elasticityType .EQ. TransLinearElasticModel) THEN +ELSE IF (obj%elasticityType .EQ. TypeElasticity%TransIsotropic) THEN CALL Display("elasticityType: TransLinearElasticModel", unitNo=unitNo) ELSE CALL Display("elasticityType: Unknown", unitNo=unitNo) @@ -285,7 +271,7 @@ CALL Display(isPlaneStress, "isPlaneStress: ", unitNo=unitNo) CALL Display(isPlaneStrain, "isPlaneStrain: ", unitNo=unitNo) -IF (obj%elasticityType .EQ. IsoLinearElasticModel) THEN +IF (obj%elasticityType .EQ. TypeElasticity%Isotropic) THEN CALL Display(obj%nu, "Poisson ratio: ", unitNo=unitNo) CALL Display(obj%G, "Shear modulus: ", unitNo=unitNo) From be1721fc6e5df1eeeeff7aee1a4db87df8c9160c Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 19:01:14 +0900 Subject: [PATCH 116/117] Update STScalarField_Class@DBCMethods.F90 Patch for issue #225 --- .../src/STScalarField_Class@DBCMethods.F90 | 69 +++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 b/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 index d44d7a9b1..193421348 100644 --- a/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 +++ b/src/submodules/STScalarField/src/STScalarField_Class@DBCMethods.F90 @@ -32,24 +32,29 @@ CALL dbc%get(nodalvalue=nodalvalue, nodenum=nodenum, times=times) -IF (SIZE(nodalvalue, 2) .EQ. 1) THEN - DO idof = 1, obj%timecompo - CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, 1), & - & timecompo=idof) - END DO - -ELSE - aint = SIZE(nodalvalue, 2) - IF (SIZE(nodalvalue, 2) .NE. obj%timeCompo) THEN +IF (PRESENT(times)) THEN + aint = SIZE(times) + IF (aint .NE. obj%timeCompo) THEN CALL e%raiseError(modName//'::'//myName//" - "// & - & '[INERNAL ERROR] :: SIZE( nodalvalue, 2 ) is '// & + & '[INERNAL ERROR] :: SIZE( times ) is '// & & tostring(aint)//' which is not equal to obj%timeCompo '// & & ' which is '//tostring(obj%timeCompo)) + RETURN END IF - CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue) + DO idof = 1, obj%timecompo + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, idof), & + & timecompo=idof) + END DO + IF (ALLOCATED(nodalvalue)) DEALLOCATE (nodalvalue) + IF (ALLOCATED(nodenum)) DEALLOCATE (nodenum) + RETURN END IF +DO idof = 1, obj%timecompo + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, 1), timecompo=idof) +END DO + IF (ALLOCATED(nodalvalue)) DEALLOCATE (nodalvalue) IF (ALLOCATED(nodenum)) DEALLOCATE (nodenum) END PROCEDURE stsField_applyDirichletBC1 @@ -64,29 +69,37 @@ INTEGER(I4B), ALLOCATABLE :: nodenum(:) INTEGER(I4B) :: idof, ii, aint -DO ii = 1, SIZE(dbc) - CALL dbc(ii)%ptr%get(nodalvalue=nodalvalue, nodenum=nodenum, & - & times=times) +IF (PRESENT(times)) THEN + aint = SIZE(times) + IF (aint .NE. obj%timeCompo) THEN + CALL e%raiseError(modName//'::'//myName//" - "// & + & '[INERNAL ERROR] :: SIZE( times ) is '// & + & tostring(aint)//' which is not equal to obj%timeCompo '// & + & ' which is '//tostring(obj%timeCompo)) + RETURN + END IF + + DO ii = 1, SIZE(dbc) + CALL dbc(ii)%ptr%get(nodalvalue=nodalvalue, nodenum=nodenum, & + & times=times) - IF (SIZE(nodalvalue, 2) .EQ. 1) THEN DO idof = 1, obj%timecompo - CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, 1), & + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, idof), & & timecompo=idof) END DO + END DO - ELSE - - aint = SIZE(nodalvalue, 2) - - IF (SIZE(nodalvalue, 2) .NE. obj%timeCompo) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & '[INERNAL ERROR] :: SIZE( nodalvalue, 2 ) is '// & - & tostring(aint)//' which is not equal to obj%timeCompo '// & - & ' which is '//tostring(obj%timeCompo)) - END IF + IF (ALLOCATED(nodalvalue)) DEALLOCATE (nodalvalue) + IF (ALLOCATED(nodenum)) DEALLOCATE (nodenum) + RETURN +END IF - CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue) - END IF +DO ii = 1, SIZE(dbc) + CALL dbc(ii)%ptr%get(nodalvalue=nodalvalue, nodenum=nodenum) + DO idof = 1, obj%timecompo + CALL obj%Set(globalNode=nodenum, VALUE=nodalvalue(:, 1), & + & timecompo=idof) + END DO END DO IF (ALLOCATED(nodalvalue)) DEALLOCATE (nodalvalue) From abb8e5a6a8cb82fa166a2966ea9cf6e22e9a1342 Mon Sep 17 00:00:00 2001 From: Vikas Sharma Date: Thu, 30 Nov 2023 21:26:14 +0900 Subject: [PATCH 117/117] Updates in VTKFile Fixing issue #230 --- .../MatrixField/src/MatrixField_Class.F90 | 93 +- src/modules/VTKFile/src/CellMethods.inc | 33 - .../VTKFile/src/ConstructorMethods.inc | 185 -- .../VTKFile/src/DataArrayAppendedMethods.inc | 304 --- src/modules/VTKFile/src/DataArrayMethods.inc | 739 ------- src/modules/VTKFile/src/FieldDataMethods.inc | 48 - src/modules/VTKFile/src/PieceMethods.inc | 82 - src/modules/VTKFile/src/PointsMethods.inc | 144 -- src/modules/VTKFile/src/TagMethods.inc | 130 -- src/modules/VTKFile/src/VTKFile_Class.F90 | 1881 +++++++++++++++-- src/modules/VTKFile/src/VertMethods.inc | 32 - .../MatrixField_Class@ConstructorMethods.F90 | 2 +- .../src/VTKFile_Class@ConstructorMethods.F90 | 110 +- 13 files changed, 1793 insertions(+), 1990 deletions(-) delete mode 100644 src/modules/VTKFile/src/CellMethods.inc delete mode 100644 src/modules/VTKFile/src/ConstructorMethods.inc delete mode 100644 src/modules/VTKFile/src/DataArrayAppendedMethods.inc delete mode 100644 src/modules/VTKFile/src/DataArrayMethods.inc delete mode 100644 src/modules/VTKFile/src/FieldDataMethods.inc delete mode 100644 src/modules/VTKFile/src/PieceMethods.inc delete mode 100644 src/modules/VTKFile/src/PointsMethods.inc delete mode 100644 src/modules/VTKFile/src/TagMethods.inc delete mode 100644 src/modules/VTKFile/src/VertMethods.inc diff --git a/src/modules/MatrixField/src/MatrixField_Class.F90 b/src/modules/MatrixField/src/MatrixField_Class.F90 index 66abeeddd..fcdd4c927 100644 --- a/src/modules/MatrixField/src/MatrixField_Class.F90 +++ b/src/modules/MatrixField/src/MatrixField_Class.F90 @@ -46,6 +46,21 @@ MODULE MatrixField_Class CHARACTER(*), PRIVATE, PARAMETER :: myPrefix = "MatrixField" INTEGER(I4B), PRIVATE, PARAMETER :: IPAR_LENGTH = 14 INTEGER(I4B), PRIVATE, PARAMETER :: FPAR_LENGTH = 14 +PUBLIC :: SetMatrixFieldParam +PUBLIC :: TypeMatrixField +PUBLIC :: MatrixField_ +PUBLIC :: SetMatrixFieldPrecondParam +PUBLIC :: SetRectangleMatrixFieldParam +PUBLIC :: DEALLOCATE +PUBLIC :: MatrixFieldCheckEssentialParam +PUBLIC :: RectangleMatrixFieldCheckEssentialParam +PUBLIC :: MatrixFieldInitiate1 +PUBLIC :: MatrixFieldInitiate2 +PUBLIC :: MatrixFieldInitiate3 +PUBLIC :: MatrixFieldDeallocate +PUBLIC :: MatrixFieldDisplay +PUBLIC :: MatrixFieldImport +PUBLIC :: MatrixFieldExport !---------------------------------------------------------------------------- ! MSRSparsity_ @@ -255,9 +270,7 @@ MODULE MatrixField_Class PROCEDURE, PUBLIC, PASS(obj) :: ApplyDBC => mField_ApplyDBC END TYPE MatrixField_ -PUBLIC :: MatrixField_ - -TYPE(MatrixField_), PARAMETER, PUBLIC :: TypeMatrixField = & +TYPE(MatrixField_), PARAMETER :: TypeMatrixField = & & MatrixField_(domains=NULL()) !---------------------------------------------------------------------------- @@ -306,8 +319,6 @@ MODULE SUBROUTINE SetMatrixFieldParam( & END SUBROUTINE SetMatrixFieldParam END INTERFACE -PUBLIC :: SetMatrixFieldParam - !---------------------------------------------------------------------------- ! SetMatrixFieldPrecondParam@sConstructorMethods !---------------------------------------------------------------------------- @@ -344,8 +355,6 @@ MODULE SUBROUTINE SetMatrixFieldPrecondParam( & END SUBROUTINE SetMatrixFieldPrecondParam END INTERFACE -PUBLIC :: SetMatrixFieldPrecondParam - !---------------------------------------------------------------------------- ! SetRectangleMatrixFieldParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -407,8 +416,6 @@ MODULE SUBROUTINE SetRectangleMatrixFieldParam( & END SUBROUTINE SetRectangleMatrixFieldParam END INTERFACE -PUBLIC :: SetRectangleMatrixFieldParam - !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -417,18 +424,12 @@ END SUBROUTINE SetRectangleMatrixFieldParam ! date: 9 Oct 2021 ! summary: Deallocates the data stored inside [[MatrixFieldPrecondition_]] -INTERFACE +INTERFACE DEALLOCATE MODULE SUBROUTINE Pmat_Deallocate(obj) TYPE(MatrixFieldPrecondition_), INTENT(INOUT) :: obj END SUBROUTINE Pmat_Deallocate -END INTERFACE - -INTERFACE DEALLOCATE - MODULE PROCEDURE Pmat_Deallocate END INTERFACE DEALLOCATE -PUBLIC :: DEALLOCATE - !---------------------------------------------------------------------------- ! Final@ConstructorMethods !---------------------------------------------------------------------------- @@ -459,8 +460,6 @@ MODULE SUBROUTINE MatrixFieldCheckEssentialParam(obj, param) END SUBROUTINE MatrixFieldCheckEssentialParam END INTERFACE -PUBLIC :: MatrixFieldCheckEssentialParam - !---------------------------------------------------------------------------- ! CheckEssentialParam@ConstructorMethods !---------------------------------------------------------------------------- @@ -481,8 +480,6 @@ MODULE SUBROUTINE RectangleMatrixFieldCheckEssentialParam(obj, param) END SUBROUTINE RectangleMatrixFieldCheckEssentialParam END INTERFACE -PUBLIC :: RectangleMatrixFieldCheckEssentialParam - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -515,20 +512,14 @@ END SUBROUTINE RectangleMatrixFieldCheckEssentialParam ! - `timeCompo`, INT, default is 1 ! - `fieldType`, INT, default is FIELD_TYPE_NORMAL -INTERFACE +INTERFACE MatrixFieldInitiate1 MODULE SUBROUTINE mField_Initiate1(obj, param, dom) CLASS(MatrixField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(Domain_), TARGET, INTENT(IN) :: dom END SUBROUTINE mField_Initiate1 -END INTERFACE - -INTERFACE MatrixFieldInitiate1 - MODULE PROCEDURE mField_Initiate1 END INTERFACE MatrixFieldInitiate1 -PUBLIC :: MatrixFieldInitiate1 - !---------------------------------------------------------------------------- ! Initiate@ConstructorMethods !---------------------------------------------------------------------------- @@ -564,7 +555,7 @@ END SUBROUTINE mField_Initiate1 ! Add functionality for other options too. !@endtodo -INTERFACE +INTERFACE MatrixFieldInitiate2 MODULE SUBROUTINE mField_Initiate2(obj, obj2, copyFull, copyStructure, & & usePointer) CLASS(MatrixField_), INTENT(INOUT) :: obj @@ -574,14 +565,8 @@ MODULE SUBROUTINE mField_Initiate2(obj, obj2, copyFull, copyStructure, & LOGICAL(LGT), OPTIONAL, INTENT(IN) :: copyStructure LOGICAL(LGT), OPTIONAL, INTENT(IN) :: usePointer END SUBROUTINE mField_Initiate2 -END INTERFACE - -INTERFACE MatrixFieldInitiate2 - MODULE PROCEDURE mField_Initiate2 END INTERFACE MatrixFieldInitiate2 -PUBLIC :: MatrixFieldInitiate2 - !---------------------------------------------------------------------------- ! Initiate@sConstructorMethods !---------------------------------------------------------------------------- @@ -590,20 +575,14 @@ END SUBROUTINE mField_Initiate2 ! date: 16 July 2021 ! summary: This routine initiates the Matrix Field -INTERFACE +INTERFACE MatrixFieldInitiate3 MODULE SUBROUTINE mField_Initiate3(obj, param, dom) CLASS(MatrixField_), INTENT(INOUT) :: obj TYPE(ParameterList_), INTENT(IN) :: param TYPE(DomainPointer_), TARGET, INTENT(IN) :: dom(:) END SUBROUTINE mField_Initiate3 -END INTERFACE - -INTERFACE MatrixFieldInitiate3 - MODULE PROCEDURE mField_Initiate3 END INTERFACE MatrixFieldInitiate3 -PUBLIC :: MatrixFieldInitiate3 - !---------------------------------------------------------------------------- ! Deallocate@ConstructorMethods !---------------------------------------------------------------------------- @@ -612,18 +591,12 @@ END SUBROUTINE mField_Initiate3 ! date: 16 July 2021 ! summary: This routine deallocates the data stored inside the matrix -INTERFACE +INTERFACE MatrixFieldDeallocate MODULE SUBROUTINE mField_Deallocate(obj) CLASS(MatrixField_), INTENT(INOUT) :: obj END SUBROUTINE mField_Deallocate -END INTERFACE - -INTERFACE MatrixFieldDeallocate - MODULE PROCEDURE mField_Deallocate END INTERFACE MatrixFieldDeallocate -PUBLIC :: MatrixFieldDeallocate - !---------------------------------------------------------------------------- ! Display@IOMethods !---------------------------------------------------------------------------- @@ -632,20 +605,14 @@ END SUBROUTINE mField_Deallocate ! date: 16 July 2021 ! summary: This routine displays the content -INTERFACE +INTERFACE MatrixFieldDisplay MODULE SUBROUTINE mField_Display(obj, msg, unitNo) CLASS(MatrixField_), INTENT(INOUT) :: obj CHARACTER(*), INTENT(IN) :: msg INTEGER(I4B), OPTIONAL, INTENT(IN) :: unitNo END SUBROUTINE mField_Display -END INTERFACE - -INTERFACE MatrixFieldDisplay - MODULE PROCEDURE mField_Display END INTERFACE MatrixFieldDisplay -PUBLIC :: MatrixFieldDisplay - !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- @@ -654,7 +621,7 @@ END SUBROUTINE mField_Display ! date: 16 July 2021 ! summary: This routine Imports the content of matrix field from hdf5file -INTERFACE +INTERFACE MatrixFieldImport MODULE SUBROUTINE mField_Import(obj, hdf5, group, dom, domains) CLASS(MatrixField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 @@ -662,14 +629,8 @@ MODULE SUBROUTINE mField_Import(obj, hdf5, group, dom, domains) TYPE(Domain_), TARGET, OPTIONAL, INTENT(IN) :: dom TYPE(DomainPointer_), TARGET, OPTIONAL, INTENT(IN) :: domains(:) END SUBROUTINE mField_Import -END INTERFACE - -INTERFACE MatrixFieldImport - MODULE PROCEDURE mField_Import END INTERFACE MatrixFieldImport -PUBLIC :: MatrixFieldImport - !---------------------------------------------------------------------------- ! Import@IOMethods !---------------------------------------------------------------------------- @@ -696,20 +657,14 @@ END SUBROUTINE mField_ImportPmat ! date: 16 July 2021 ! summary: This routine Exports the content of matrixfield_ to hdf5 file -INTERFACE +INTERFACE MatrixFieldExport MODULE SUBROUTINE mField_Export(obj, hdf5, group) CLASS(MatrixField_), INTENT(INOUT) :: obj TYPE(HDF5File_), INTENT(INOUT) :: hdf5 CHARACTER(*), INTENT(IN) :: group END SUBROUTINE mField_Export -END INTERFACE - -INTERFACE MatrixFieldExport - MODULE PROCEDURE mField_Export END INTERFACE MatrixFieldExport -PUBLIC :: MatrixFieldExport - !---------------------------------------------------------------------------- ! ExportPmat@IOMethods !---------------------------------------------------------------------------- diff --git a/src/modules/VTKFile/src/CellMethods.inc b/src/modules/VTKFile/src/CellMethods.inc deleted file mode 100644 index ed1057df6..000000000 --- a/src/modules/VTKFile/src/CellMethods.inc +++ /dev/null @@ -1,33 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WriteCells@CellMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 sept 2021 -! summary: Write Cells - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteCells( obj, connectivity, offsets, types ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: connectivity( : ) - INTEGER( I4B ), INTENT( IN ) :: offsets( : ) - INTEGER( Int8 ), INTENT( IN ) :: types( : ) -END SUBROUTINE VTKFile_WriteCells -END INTERFACE diff --git a/src/modules/VTKFile/src/ConstructorMethods.inc b/src/modules/VTKFile/src/ConstructorMethods.inc deleted file mode 100644 index f6205a112..000000000 --- a/src/modules/VTKFile/src/ConstructorMethods.inc +++ /dev/null @@ -1,185 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! VTKFile@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: This function returns an instance of VTKFile -! -!# Introduction -! This function returns an instance if VTKFile. After calling this function -! This routine initiates the XMLFile, and opens it. -! It also write header file and DataStructure tag to the file. -! -!## Arguments: -! -! *filename*: is the name of the file -! -! *mode* : can be `READ`, `WRITE`, `NEW`, `OVERWRITE`. It is like action. -! -! *DataFormat* : defines the format of DataArray in VTKFile, it can be one fo -! the following: -! -! - `VTK_ASCII` -! - `VTK_BINARY` -! - `VTK_APPENED` -! - `VTK_RAW_APPENED`, -! - `VTK_BINARY_APPENDED`. -! - `VTK_APPENDED` and `VTK_RAW_APPENDED` are the same, where appended data -! is in raw format -! - `VTK_BINARY_APPENDED`, on the other hand, appends data in binary form -! -! *DataStructureType* : The type of vtk file. It can have following values -! -! - ImageData, -! - RectilinearGrid, -! - StructuredGrid, -! - PolyData, -! - UnstructuredGrid -! - PImageData -! - PRectilinearGrid -! - PStructuredGrid -! - PPolyData -! - PUnstructuredGrid -! -! *WholeExtent* : is [x1, x2, y1, y2, z1, z2], it is required for structured -! data set. -! -! *isVolatile* : It is True if volatileBuffer is used to keep the xml file -! -! *meshDataFormat* It can be Float32, Float64 - -INTERFACE - MODULE SUBROUTINE InitiateVTKFile(obj, filename, mode, DataFormat, & - & DataStructureType, WholeExtent, isVolatile, meshDataFormat, & - & Spacing, Origin) - CLASS(VTKFile_), INTENT(INOUT) :: obj - CHARACTER(LEN=*), INTENT(IN) :: filename - !! Name of the file, where xml data will be printed - CHARACTER(LEN=*), INTENT(IN) :: mode - !! READ, WRITE, NEW, REPLACE - INTEGER(I4B), INTENT(IN) :: DataFormat - !! VTK_ASCII, VTK_APPENEDED, VTK_BINARY - INTEGER(I4B), INTENT(IN) :: DataStructureType - !! VTK_IMAGEDATA, VTK_STRUCTUREDGRID, etc. - INTEGER(I4B), OPTIONAL, INTENT(IN) :: WholeExtent(:) - !! Required for structured data set - !! [x1, x2, y1, y2, z1, z2] - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isVolatile - !! True if volatileBuffer is used to keep the xml file - CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: meshDataFormat - !! Float32, Float64, etc - INTEGER(I4B), OPTIONAL, INTENT(IN) :: Spacing(:) - !! dx, dy, dz, needed in case of ImageData - INTEGER(I4B), OPTIONAL, INTENT(IN) :: Origin(:) - !! x0, y0, z0, needed in case of ImageData - END SUBROUTINE InitiateVTKFile -END INTERFACE - -!---------------------------------------------------------------------------- -! Deallocate@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Deallocates the content of VTKFile and close or delete it. - -INTERFACE - MODULE SUBROUTINE VTKFile_Deallocate(obj, delete) - CLASS(VTKFile_), INTENT(INOUT) :: obj - LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete - END SUBROUTINE VTKFile_Deallocate -END INTERFACE - -!---------------------------------------------------------------------------- -! Final@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Finalizer for VTKFile - -INTERFACE - MODULE SUBROUTINE VTKFile_Final(obj) - TYPE(VTKFile_), INTENT(INOUT) :: obj - END SUBROUTINE VTKFile_Final -END INTERFACE - -!---------------------------------------------------------------------------- -! UpdateOffset@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 7 July 2022 -! summary: Update the offset in VTKFile -! -!# Introduction -! -! If the Dataformat is VTK_APPENDED then update the offset by number of -! bytes `nByte` - -INTERFACE - MODULE ELEMENTAL SUBROUTINE VTKFile_UpdateOffset(obj, nByte) - CLASS(VTKFile_), INTENT(INOUT) :: obj - INTEGER(I4B), INTENT(IN) :: nByte - END SUBROUTINE VTKFile_UpdateOffset -END INTERFACE - -!---------------------------------------------------------------------------- -! Close@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Close the file - -INTERFACE - MODULE SUBROUTINE VTKFile_Close(obj) - CLASS(VTKFile_), INTENT(INOUT) :: obj - END SUBROUTINE VTKFile_Close -END INTERFACE - -!---------------------------------------------------------------------------- -! OpenScratchFile@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 7 July 2022 -! summary: Open the scratch file if data format is `VTK_APPENDED` - -INTERFACE - MODULE SUBROUTINE VTKFile_OpenScratchFile(obj) - CLASS(VTKFile_), INTENT(INOUT) :: obj - END SUBROUTINE VTKFile_OpenScratchFile -END INTERFACE - -!---------------------------------------------------------------------------- -! CloseScratchFile@ConstructorMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 7 July 2022 -! summary: Close the scratch file - -INTERFACE - MODULE SUBROUTINE VTKFile_CloseScratchFile(obj) - CLASS(VTKFile_), INTENT(INOUT) :: obj - END SUBROUTINE VTKFile_CloseScratchFile -END INTERFACE diff --git a/src/modules/VTKFile/src/DataArrayAppendedMethods.inc b/src/modules/VTKFile/src/DataArrayAppendedMethods.inc deleted file mode 100644 index 073f5343b..000000000 --- a/src/modules/VTKFile/src/DataArrayAppendedMethods.inc +++ /dev/null @@ -1,304 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Appended( obj ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj -END SUBROUTINE VTKFile_WriteDataArray_Appended -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch1( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - CLASS( * ), INTENT( IN ) :: x( 1: ) -END SUBROUTINE VTKFile_WriteToScratch1 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch2( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - CLASS( * ), INTENT( IN ) :: x( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch2 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch3( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - CLASS( * ), INTENT( IN ) :: x( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch3 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch4( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - CLASS( * ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch4 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch5( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( 1: ) - REAL( Real64 ), INTENT( IN ) :: y( 1: ) - REAL( Real64 ), INTENT( IN ) :: z( 1: ) -END SUBROUTINE VTKFile_WriteToScratch5 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch6( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( 1: ) - REAL( Real32 ), INTENT( IN ) :: y( 1: ) - REAL( Real32 ), INTENT( IN ) :: z( 1: ) -END SUBROUTINE VTKFile_WriteToScratch6 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch7( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int64 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int64 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int64 ), INTENT( IN ) :: z( 1: ) -END SUBROUTINE VTKFile_WriteToScratch7 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch8( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int32 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int32 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int32 ), INTENT( IN ) :: z( 1: ) -END SUBROUTINE VTKFile_WriteToScratch8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch9( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int16 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int16 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int16 ), INTENT( IN ) :: z( 1: ) -END SUBROUTINE VTKFile_WriteToScratch9 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch10( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int8 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int8 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int8 ), INTENT( IN ) :: z( 1: ) -END SUBROUTINE VTKFile_WriteToScratch10 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch11( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: y( 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: z( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch11 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch12( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: y( 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: z( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch12 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch13( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: z( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch13 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch14( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: z( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch14 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch15( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: z( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch15 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch16( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: z( 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch17( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: z( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch17 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch18( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: z( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch18 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch19( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: z( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch19 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch20( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: z( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch20 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch21( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: z( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch21 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteToScratch@DataArrayAppendedMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteToScratch22( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: z( 1:, 1:, 1: ) -END SUBROUTINE VTKFile_WriteToScratch22 -END INTERFACE diff --git a/src/modules/VTKFile/src/DataArrayMethods.inc b/src/modules/VTKFile/src/DataArrayMethods.inc deleted file mode 100644 index 3d5c416d6..000000000 --- a/src/modules/VTKFile/src/DataArrayMethods.inc +++ /dev/null @@ -1,739 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WriteDataArrayLocationTag@DataArrayMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: WriteDataArrayLocation CELL or NODE -! -!# Introduction -! -! Write PointData or CellData open/close tag. -! -!@note -! This routine must be called before saving the data related to geometric -! mesh, this function initializes the saving of data variables indicating -! the *location* (node or cell centered) of variables that will be saved. -!@endnote -! -!@note -! A single file can contain both cell and node centered variables. -!@endnote -! - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArrayLocationTag( obj, location, action ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: location - !! "CELL" and "NODE" - TYPE( String ), INTENT( IN ) :: action - !! "OPEN" or "CLOSE" -END SUBROUTINE VTKFile_WriteDataArrayLocationTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArrayTag@DataArrayMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: WriteDataArrayTag - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArrayTag( obj, dataType, name, & - & numberOfComponents, content, isTuples, isOffset ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: dataType - TYPE( String ), INTENT( IN ) :: name - INTEGER( I4B ), INTENT( IN ) :: numberOfComponents - TYPE( String ), OPTIONAL, INTENT( IN ) :: content - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isOffset -END SUBROUTINE VTKFile_WriteDataArrayTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: This routine writes Rank1 array of Real32 -! -!# Introduction -! -! This routine writes Rank 1 of Real32. This routine calls `WriteDataArrayTag` - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank1_Real32( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents - !! number of components in the data, default is 1 -END SUBROUTINE VTKFile_WriteDataArray_Rank1_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: This routine writes Rank1 array of Real64 - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank1_Real64( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank1_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: This routine writes Rank1 array of Int8 - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank1_Int8( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank1_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: This routine writes Rank1 array of Int16 - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank1_Int16( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank1_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank1_Int32(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank1_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank1_Int64(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank1_Int64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank2_Real32( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank2_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank2_Real64( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank2_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank2_Int8( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank2_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank2_Int16( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank2_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank2_Int32(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank2_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank2_Int64(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank2_Int64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank3_Real32( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank3_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank3_Real64( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank3_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank3_Int8( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank3_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank3_Int16( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank3_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank3_Int32(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank3_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank3_Int64(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank3_Int64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank4_Real32( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank4_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank4_Real64( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank4_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank4_Int8( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank4_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank4_Int16( obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank4_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank4_Int32(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank4_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_Rank4_Int64(obj, name, x, & - & isTuples, numberOfComponents ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples - INTEGER( I4B ), OPTIONAL, INTENT( IN ) :: numberOfComponents -END SUBROUTINE VTKFile_WriteDataArray_Rank4_Int64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Real32( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1: ) - REAL( Real32 ), INTENT( IN ) :: y( 1: ) - REAL( Real32 ), INTENT( IN ) :: z( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Real64( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1: ) - REAL( Real64 ), INTENT( IN ) :: y( 1: ) - REAL( Real64 ), INTENT( IN ) :: z( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int8( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int8 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int8 ), INTENT( IN ) :: z( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int16( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int16 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int16 ), INTENT( IN ) :: z( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int32( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int32 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int32 ), INTENT( IN ) :: z( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int64( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1: ) - INTEGER( Int64 ), INTENT( IN ) :: y( 1: ) - INTEGER( Int64 ), INTENT( IN ) :: z( 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank1_Int64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Real32( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: y( 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: z( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Real64( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: y( 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: z( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int8( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: z( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int16( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: z( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int32( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: z( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int64( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: y( 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: z( 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank2_Int64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Real32( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - REAL( Real32 ), INTENT( IN ) :: z( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Real32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Real64( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - REAL( Real64 ), INTENT( IN ) :: z( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Real64 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int8( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int8 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int8 ), INTENT( IN ) :: z( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int8 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int16( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int16 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int16 ), INTENT( IN ) :: z( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int16 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int32( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int32 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int32 ), INTENT( IN ) :: z( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int32 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataArray@DataArrayMethods -!---------------------------------------------------------------------------- - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int64( obj, name, x, & - & y, z, isTuples ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - INTEGER( Int64 ), INTENT( IN ) :: x( 1:, 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: y( 1:, 1:, 1: ) - INTEGER( Int64 ), INTENT( IN ) :: z( 1:, 1:, 1: ) - LOGICAL( LGT ), OPTIONAL, INTENT( IN ) :: isTuples -END SUBROUTINE VTKFile_WriteDataArray_XYZ_Rank3_Int64 -END INTERFACE diff --git a/src/modules/VTKFile/src/FieldDataMethods.inc b/src/modules/VTKFile/src/FieldDataMethods.inc deleted file mode 100644 index d438b56a0..000000000 --- a/src/modules/VTKFile/src/FieldDataMethods.inc +++ /dev/null @@ -1,48 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WriteFieldData@FieldDataMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write Field Data - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteFieldData_1( obj, name, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - CLASS( * ), INTENT( IN ) :: x -END SUBROUTINE VTKFile_WriteFieldData_1 -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteFieldData@FieldDataMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write Field Data - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteFieldData_2( obj, action ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: action - !! Open, Close -END SUBROUTINE VTKFile_WriteFieldData_2 -END INTERFACE diff --git a/src/modules/VTKFile/src/PieceMethods.inc b/src/modules/VTKFile/src/PieceMethods.inc deleted file mode 100644 index bf7f292c6..000000000 --- a/src/modules/VTKFile/src/PieceMethods.inc +++ /dev/null @@ -1,82 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WritePiece@PieceMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: WritePiece - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePiece_1( obj, extent, srcFileName ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: extent( : ) - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: srcFileName -END SUBROUTINE VTKFile_WritePiece_1 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePiece@PieceMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write Piece - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePiece_2( obj, nPoints, nCells ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: nPoints - INTEGER( I4B ), INTENT( IN ) :: nCells -END SUBROUTINE VTKFile_WritePiece_2 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePiece@PieceMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write Piece - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePiece_3( obj, nPoints, nVerts, nLines, & - & nStrips, nPolys ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: nPoints - INTEGER( I4B ), INTENT( IN ) :: nVerts - INTEGER( I4B ), INTENT( IN ) :: nLines - INTEGER( I4B ), INTENT( IN ) :: nStrips - INTEGER( I4B ), INTENT( IN ) :: nPolys -END SUBROUTINE VTKFile_WritePiece_3 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePiece@PieceMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write piece - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePiece_4( obj ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj -END SUBROUTINE VTKFile_WritePiece_4 -END INTERFACE diff --git a/src/modules/VTKFile/src/PointsMethods.inc b/src/modules/VTKFile/src/PointsMethods.inc deleted file mode 100644 index 562564df8..000000000 --- a/src/modules/VTKFile/src/PointsMethods.inc +++ /dev/null @@ -1,144 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write Points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_1( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( : ) - REAL( Real64 ), INTENT( IN ) :: y( : ) - REAL( Real64 ), INTENT( IN ) :: z( : ) -END SUBROUTINE VTKFile_WritePoints_1 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_2( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( : ) - REAL( Real32 ), INTENT( IN ) :: y( : ) - REAL( Real32 ), INTENT( IN ) :: z( : ) -END SUBROUTINE VTKFile_WritePoints_2 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_3( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( 1:, 1: ) -END SUBROUTINE VTKFile_WritePoints_3 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_4( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( 1:, 1: ) -END SUBROUTINE VTKFile_WritePoints_4 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_5( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( :, :, : ) - REAL( Real64 ), INTENT( IN ) :: y( :, :, : ) - REAL( Real64 ), INTENT( IN ) :: z( :, :, : ) -END SUBROUTINE VTKFile_WritePoints_5 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_6( obj, x, y, z ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( :, :, : ) - REAL( Real32 ), INTENT( IN ) :: y( :, :, : ) - REAL( Real32 ), INTENT( IN ) :: z( :, :, : ) -END SUBROUTINE VTKFile_WritePoints_6 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_7( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real64 ), INTENT( IN ) :: x( :, :, :, : ) -END SUBROUTINE VTKFile_WritePoints_7 -END INTERFACE - -!---------------------------------------------------------------------------- -! WritePoints@PointsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 Sept 2021 -! summary: Write points - -INTERFACE -MODULE SUBROUTINE VTKFile_WritePoints_8( obj, x ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - REAL( Real32 ), INTENT( IN ) :: x( :, :, :, : ) -END SUBROUTINE VTKFile_WritePoints_8 -END INTERFACE diff --git a/src/modules/VTKFile/src/TagMethods.inc b/src/modules/VTKFile/src/TagMethods.inc deleted file mode 100644 index fc6c3c068..000000000 --- a/src/modules/VTKFile/src/TagMethods.inc +++ /dev/null @@ -1,130 +0,0 @@ -! 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 -! - - -!---------------------------------------------------------------------------- -! WriteRootTag@TagsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 7 July 2022 -! summary: Write the root tag -! -!# Introduction -! -! This routine write the root tag. This routine is called when we initiate -! the VTKFile. following information is written. Also indent is set to 2. -! -!```xml -! -! -!``` - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteRootTag( obj ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj -END SUBROUTINE VTKFile_WriteRootTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteDataStructureTag@TagsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 7 July 2022 -! summary: Write the data structure tags - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteDataStructureTag( obj, meshDataFormat ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - CHARACTER( LEN = * ), OPTIONAL, INTENT( IN ) :: meshDataFormat - !! Float32, Float64 - !! It should be present for parallel data structure - !! PARALLEL_VTK_RECTILINEARGRID, PARALLEL_VTK_STRUCTUREDGRID, - !! PARALLEL_VTK_UNSTRUCTUREDGRID -END SUBROUTINE VTKFile_WriteDataStructureTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteStartTag@TagsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Write the start tag - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteStartTag( obj, name, attrNames, attrValues ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - TYPE( String ), OPTIONAL, INTENT( IN ) :: attrNames( : ) - TYPE( String ), OPTIONAL, INTENT( IN ) :: attrValues( : ) -END SUBROUTINE VTKFile_WriteStartTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteEndTag@TagsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Write the End tag - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteEndTag( obj, name ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name -END SUBROUTINE VTKFile_WriteEndTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteSelfClosingTag@TagsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Write the self closing tag - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteSelfClosingTag( obj, name, attrNames, & - & attrValues ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - TYPE( String ), INTENT( IN ) :: name - TYPE( String ), OPTIONAL, INTENT( IN ) :: attrNames( : ) - TYPE( String ), OPTIONAL, INTENT( IN ) :: attrValues( : ) -END SUBROUTINE VTKFile_WriteSelfClosingTag -END INTERFACE - -!---------------------------------------------------------------------------- -! WriteTag@TagsMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 13 Sept 2021 -! summary: Write Tags and contents - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteTag( obj, name, attrNames, & - & attrValues, content ) - CLASS( VTKFile_ ), 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 VTKFile_WriteTag -END INTERFACE diff --git a/src/modules/VTKFile/src/VTKFile_Class.F90 b/src/modules/VTKFile/src/VTKFile_Class.F90 index 3f006a159..acbc1eec3 100644 --- a/src/modules/VTKFile/src/VTKFile_Class.F90 +++ b/src/modules/VTKFile/src/VTKFile_Class.F90 @@ -16,39 +16,39 @@ ! MODULE VTKFile_Class -USE GlobalData +USE Globaldata USE BaseType USE String_Class, ONLY: String -USE VTKDataArrayEncoder +USE VTKdataArrayEncoder USE XMLFile_Class USE ExceptionHandler_Class, ONLY: e IMPLICIT NONE PRIVATE -!! -PUBLIC :: encodeVTKDataArray + +PUBLIC :: encodeVTKdataArray CHARACTER(*), PARAMETER :: modName = "VTKFile_Class" -INTEGER(I4B), PARAMETER :: MAX_LEN_DATA_STRUCTURENAME = 256 -INTEGER(I4B), PARAMETER, PUBLIC :: VTK_ImageData = 1 +INTEGER(I4B), PARAMETER :: MAX_LEN_data_STRUCTURENAME = 256 +INTEGER(I4B), PARAMETER, PUBLIC :: VTK_Imagedata = 1 INTEGER(I4B), PARAMETER, PUBLIC :: VTK_RectilinearGrid = 2 INTEGER(I4B), PARAMETER, PUBLIC :: VTK_StructuredGrid = 3 -INTEGER(I4B), PARAMETER, PUBLIC :: VTK_PolyData = 4 +INTEGER(I4B), PARAMETER, PUBLIC :: VTK_Polydata = 4 INTEGER(I4B), PARAMETER, PUBLIC :: VTK_UnstructuredGrid = 5 -INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_ImageData = 6 +INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_Imagedata = 6 INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_RectilinearGrid = 7 INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_StructuredGrid = 8 -INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_PolyData = 9 +INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_Polydata = 9 INTEGER(I4B), PARAMETER, PUBLIC :: PARALLEL_VTK_UnstructuredGrid = 10 -CHARACTER(*), PARAMETER, DIMENSION(10) :: DataStructureName = & +CHARACTER(*), PARAMETER, DIMENSION(10) :: dataStructureName = & & [ & - & "ImageData ", & + & "Imagedata ", & & "RectilinearGrid ", & & "StructuredGrid ", & - & "PolyData ", & + & "Polydata ", & & "UnstructuredGrid ", & - & "PImageData ", & + & "PImagedata ", & & "PRectilinearGrid ", & & "PStructuredGrid ", & - & "PPolyData ", & + & "PPolydata ", & & "PUnstructuredGrid" & & ] INTEGER(I4B), PARAMETER, PUBLIC :: VTK_ASCII = 1 @@ -56,12 +56,14 @@ MODULE VTKFile_Class INTEGER(I4B), PARAMETER, PUBLIC :: VTK_APPENDED = 3 INTEGER(I4B), PARAMETER, PUBLIC :: VTK_RAW_APPENDED = 3 INTEGER(I4B), PARAMETER, PUBLIC :: VTK_BINARY_APPENDED = 4 -CHARACTER(*), PARAMETER, DIMENSION(3) :: DataFormatName = & +CHARACTER(*), PARAMETER, DIMENSION(3) :: dataFormatName = & & [ & & "ascii ", & & "binary ", & & "appended" & & ] +PUBLIC :: VTKFile_ +PUBLIC :: VTKFilePointer_ !---------------------------------------------------------------------------- ! VTKFile_ @@ -76,26 +78,26 @@ MODULE VTKFile_Class LOGICAL(LGT) :: isStructured = .FALSE. !! Is dataset structured INTEGER(I4B) :: dataStructureType = 0 - !! 1 : VTK_ImageData + !! 1 : VTK_Imagedata !! 2 : VTK_RectilinearGrid !! 3 : VTK_StructuredGrid - !! 4 : VTK_PolyData + !! 4 : VTK_Polydata !! 5 : VTK_UnstructuredGrid - !! 6 : PARALLEL_VTK_ImageData + !! 6 : PARALLEL_VTK_Imagedata !! 7 : PARALLEL_VTK_RectilinearGrid !! 8 : PARALLEL_VTK_StructuredGrid - !! 9 : PARALLEL_VTK_PolyData + !! 9 : PARALLEL_VTK_Polydata !! 10: PARALLEL_VTK_UnstructuredGrid - CHARACTER(MAX_LEN_DATA_STRUCTURENAME) :: dataStructureName - !! ImageData, + CHARACTER(MAX_LEN_data_STRUCTURENAME) :: dataStructureName + !! Imagedata, !! RectilinearGrid, !! StructuredGrid, - !! PolyData, + !! Polydata, !! UnstructuredGrid - !! PImageData + !! PImagedata !! PRectilinearGrid !! PStructuredGrid - !! PPolyData + !! PPolydata !! PUnstructuredGrid INTEGER(I4B) :: dataFormat = 0 !! VTK_ASCII @@ -106,9 +108,9 @@ MODULE VTKFile_Class INTEGER(I4B) :: wholeExtent(6) = 0 !! Whole extent INTEGER(I4B) :: origin(3) = 0 - !! x0, y0, z0, Origin needed for ImageData + !! x0, y0, z0, Origin needed for Imagedata INTEGER(I4B) :: SPACING(3) = 1 - !! dx, dy, dz needed for ImageData + !! dx, dy, dz needed for Imagedata INTEGER(I4B) :: indent = 0 !! Indent INTEGER(I4B) :: offset = 0 @@ -121,9 +123,9 @@ MODULE VTKFile_Class TYPE(String) :: volatileBuffer CONTAINS PRIVATE - !! - !! @ConstructorMethods - !! + + ! CONSTRUCTOR: + ! @ConstructorMethods PROCEDURE, PUBLIC, PASS(obj) :: InitiateVTKFile PROCEDURE, PUBLIC, PASS(obj) :: DEALLOCATE => VTKFile_Deallocate FINAL :: VTKFile_Final @@ -131,125 +133,125 @@ MODULE VTKFile_Class PROCEDURE, PASS(obj) :: UpdateOffset => VTKFile_UpdateOffset PROCEDURE, PASS(obj) :: OpenScratchFile => VTKFile_OpenScratchFile PROCEDURE, PASS(obj) :: CloseScratchFile => VTKFile_CloseScratchFile - !! - !! @TagsMethods - !! + + ! IO: + ! @TagsMethods PROCEDURE, PUBLIC, PASS(obj) :: WriteRootTag => VTKFile_WriteRootTag - PROCEDURE, PUBLIC, PASS(obj) :: WriteDataStructureTag => & - & VTKFile_WriteDataStructureTag + PROCEDURE, PUBLIC, PASS(obj) :: WritedataStructureTag => & + & VTKFile_WritedataStructureTag PROCEDURE, PUBLIC, PASS(obj) :: WriteStartTag => VTKFile_WriteStartTag PROCEDURE, PUBLIC, PASS(obj) :: WriteEndTag => VTKFile_WriteEndTag PROCEDURE, PUBLIC, PASS(obj) :: WriteSelfClosingTag => & & VTKFile_WriteSelfClosingTag PROCEDURE, PUBLIC, PASS(obj) :: WriteTag => VTKFile_WriteTag - !! - !! @VertMethods - !! + + ! IO: + ! @VertMethods PROCEDURE, PUBLIC, PASS(obj) :: WriteVerts => VTKFile_WriteVerts - !! - !! @CellMethods - !! + + ! IO: + ! @CellMethods PROCEDURE, PUBLIC, PASS(obj) :: WriteCells => VTKFile_WriteCells - !! - !! @DataArrayMethods - !! - PROCEDURE, PUBLIC, PASS(obj) :: WriteDataArrayTag => & - & VTKFile_WriteDataArrayTag - PROCEDURE, PUBLIC, PASS(obj) :: WriteDataArrayLocationTag => & - & VTKFile_WriteDataArrayLocationTag + + ! IO: + ! @dataArrayMethods + PROCEDURE, PUBLIC, PASS(obj) :: WritedataArrayTag => & + & VTKFile_WritedataArrayTag + PROCEDURE, PUBLIC, PASS(obj) :: WritedataArrayLocationTag => & + & VTKFile_WritedataArrayLocationTag PROCEDURE, PASS(obj) :: & - & VTKFile_WriteDataArrayLocationTag, & - & VTKFile_WriteDataArray_Rank1_Real32, & - & VTKFile_WriteDataArray_Rank1_Real64, & - & VTKFile_WriteDataArray_Rank1_Int64, & - & VTKFile_WriteDataArray_Rank1_Int32, & - & VTKFile_WriteDataArray_Rank1_Int16, & - & VTKFile_WriteDataArray_Rank1_Int8, & - & VTKFile_WriteDataArray_Rank2_Real32, & - & VTKFile_WriteDataArray_Rank2_Real64, & - & VTKFile_WriteDataArray_Rank2_Int64, & - & VTKFile_WriteDataArray_Rank2_Int32, & - & VTKFile_WriteDataArray_Rank2_Int16, & - & VTKFile_WriteDataArray_Rank2_Int8, & - & VTKFile_WriteDataArray_Rank3_Real32, & - & VTKFile_WriteDataArray_Rank3_Real64, & - & VTKFile_WriteDataArray_Rank3_Int64, & - & VTKFile_WriteDataArray_Rank3_Int32, & - & VTKFile_WriteDataArray_Rank3_Int16, & - & VTKFile_WriteDataArray_Rank3_Int8, & - & VTKFile_WriteDataArray_Rank4_Real32, & - & VTKFile_WriteDataArray_Rank4_Real64, & - & VTKFile_WriteDataArray_Rank4_Int64, & - & VTKFile_WriteDataArray_Rank4_Int32, & - & VTKFile_WriteDataArray_Rank4_Int16, & - & VTKFile_WriteDataArray_Rank4_Int8, & - & VTKFile_WriteDataArray_XYZ_Rank1_Real32, & - & VTKFile_WriteDataArray_XYZ_Rank1_Real64, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int64, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int32, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int16, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int8, & - & VTKFile_WriteDataArray_XYZ_Rank2_Real32, & - & VTKFile_WriteDataArray_XYZ_Rank2_Real64, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int64, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int32, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int16, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int8, & - & VTKFile_WriteDataArray_XYZ_Rank3_Real32, & - & VTKFile_WriteDataArray_XYZ_Rank3_Real64, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int64, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int32, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int16, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int8 - GENERIC, PUBLIC :: WriteDataArray => & - & VTKFile_WriteDataArrayLocationTag, & - & VTKFile_WriteDataArray_Rank1_Real32, & - & VTKFile_WriteDataArray_Rank1_Real64, & - & VTKFile_WriteDataArray_Rank1_Int64, & - & VTKFile_WriteDataArray_Rank1_Int32, & - & VTKFile_WriteDataArray_Rank1_Int16, & - & VTKFile_WriteDataArray_Rank1_Int8, & - & VTKFile_WriteDataArray_Rank2_Real32, & - & VTKFile_WriteDataArray_Rank2_Real64, & - & VTKFile_WriteDataArray_Rank2_Int64, & - & VTKFile_WriteDataArray_Rank2_Int32, & - & VTKFile_WriteDataArray_Rank2_Int16, & - & VTKFile_WriteDataArray_Rank2_Int8, & - & VTKFile_WriteDataArray_Rank3_Real32, & - & VTKFile_WriteDataArray_Rank3_Real64, & - & VTKFile_WriteDataArray_Rank3_Int64, & - & VTKFile_WriteDataArray_Rank3_Int32, & - & VTKFile_WriteDataArray_Rank3_Int16, & - & VTKFile_WriteDataArray_Rank3_Int8, & - & VTKFile_WriteDataArray_Rank4_Real32, & - & VTKFile_WriteDataArray_Rank4_Real64, & - & VTKFile_WriteDataArray_Rank4_Int64, & - & VTKFile_WriteDataArray_Rank4_Int32, & - & VTKFile_WriteDataArray_Rank4_Int16, & - & VTKFile_WriteDataArray_Rank4_Int8, & - & VTKFile_WriteDataArray_XYZ_Rank1_Real32, & - & VTKFile_WriteDataArray_XYZ_Rank1_Real64, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int64, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int32, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int16, & - & VTKFile_WriteDataArray_XYZ_Rank1_Int8, & - & VTKFile_WriteDataArray_XYZ_Rank2_Real32, & - & VTKFile_WriteDataArray_XYZ_Rank2_Real64, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int64, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int32, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int16, & - & VTKFile_WriteDataArray_XYZ_Rank2_Int8, & - & VTKFile_WriteDataArray_XYZ_Rank3_Real32, & - & VTKFile_WriteDataArray_XYZ_Rank3_Real64, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int64, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int32, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int16, & - & VTKFile_WriteDataArray_XYZ_Rank3_Int8 - !! - !! @DataArrayAppendedMethods - !! + & VTKFile_WritedataArrayLocationTag, & + & VTKFile_WritedataArray_Rank1_Real32, & + & VTKFile_WritedataArray_Rank1_Real64, & + & VTKFile_WritedataArray_Rank1_Int64, & + & VTKFile_WritedataArray_Rank1_Int32, & + & VTKFile_WritedataArray_Rank1_Int16, & + & VTKFile_WritedataArray_Rank1_Int8, & + & VTKFile_WritedataArray_Rank2_Real32, & + & VTKFile_WritedataArray_Rank2_Real64, & + & VTKFile_WritedataArray_Rank2_Int64, & + & VTKFile_WritedataArray_Rank2_Int32, & + & VTKFile_WritedataArray_Rank2_Int16, & + & VTKFile_WritedataArray_Rank2_Int8, & + & VTKFile_WritedataArray_Rank3_Real32, & + & VTKFile_WritedataArray_Rank3_Real64, & + & VTKFile_WritedataArray_Rank3_Int64, & + & VTKFile_WritedataArray_Rank3_Int32, & + & VTKFile_WritedataArray_Rank3_Int16, & + & VTKFile_WritedataArray_Rank3_Int8, & + & VTKFile_WritedataArray_Rank4_Real32, & + & VTKFile_WritedataArray_Rank4_Real64, & + & VTKFile_WritedataArray_Rank4_Int64, & + & VTKFile_WritedataArray_Rank4_Int32, & + & VTKFile_WritedataArray_Rank4_Int16, & + & VTKFile_WritedataArray_Rank4_Int8, & + & VTKFile_WritedataArray_XYZ_Rank1_Real32, & + & VTKFile_WritedataArray_XYZ_Rank1_Real64, & + & VTKFile_WritedataArray_XYZ_Rank1_Int64, & + & VTKFile_WritedataArray_XYZ_Rank1_Int32, & + & VTKFile_WritedataArray_XYZ_Rank1_Int16, & + & VTKFile_WritedataArray_XYZ_Rank1_Int8, & + & VTKFile_WritedataArray_XYZ_Rank2_Real32, & + & VTKFile_WritedataArray_XYZ_Rank2_Real64, & + & VTKFile_WritedataArray_XYZ_Rank2_Int64, & + & VTKFile_WritedataArray_XYZ_Rank2_Int32, & + & VTKFile_WritedataArray_XYZ_Rank2_Int16, & + & VTKFile_WritedataArray_XYZ_Rank2_Int8, & + & VTKFile_WritedataArray_XYZ_Rank3_Real32, & + & VTKFile_WritedataArray_XYZ_Rank3_Real64, & + & VTKFile_WritedataArray_XYZ_Rank3_Int64, & + & VTKFile_WritedataArray_XYZ_Rank3_Int32, & + & VTKFile_WritedataArray_XYZ_Rank3_Int16, & + & VTKFile_WritedataArray_XYZ_Rank3_Int8 + GENERIC, PUBLIC :: WritedataArray => & + & VTKFile_WritedataArrayLocationTag, & + & VTKFile_WritedataArray_Rank1_Real32, & + & VTKFile_WritedataArray_Rank1_Real64, & + & VTKFile_WritedataArray_Rank1_Int64, & + & VTKFile_WritedataArray_Rank1_Int32, & + & VTKFile_WritedataArray_Rank1_Int16, & + & VTKFile_WritedataArray_Rank1_Int8, & + & VTKFile_WritedataArray_Rank2_Real32, & + & VTKFile_WritedataArray_Rank2_Real64, & + & VTKFile_WritedataArray_Rank2_Int64, & + & VTKFile_WritedataArray_Rank2_Int32, & + & VTKFile_WritedataArray_Rank2_Int16, & + & VTKFile_WritedataArray_Rank2_Int8, & + & VTKFile_WritedataArray_Rank3_Real32, & + & VTKFile_WritedataArray_Rank3_Real64, & + & VTKFile_WritedataArray_Rank3_Int64, & + & VTKFile_WritedataArray_Rank3_Int32, & + & VTKFile_WritedataArray_Rank3_Int16, & + & VTKFile_WritedataArray_Rank3_Int8, & + & VTKFile_WritedataArray_Rank4_Real32, & + & VTKFile_WritedataArray_Rank4_Real64, & + & VTKFile_WritedataArray_Rank4_Int64, & + & VTKFile_WritedataArray_Rank4_Int32, & + & VTKFile_WritedataArray_Rank4_Int16, & + & VTKFile_WritedataArray_Rank4_Int8, & + & VTKFile_WritedataArray_XYZ_Rank1_Real32, & + & VTKFile_WritedataArray_XYZ_Rank1_Real64, & + & VTKFile_WritedataArray_XYZ_Rank1_Int64, & + & VTKFile_WritedataArray_XYZ_Rank1_Int32, & + & VTKFile_WritedataArray_XYZ_Rank1_Int16, & + & VTKFile_WritedataArray_XYZ_Rank1_Int8, & + & VTKFile_WritedataArray_XYZ_Rank2_Real32, & + & VTKFile_WritedataArray_XYZ_Rank2_Real64, & + & VTKFile_WritedataArray_XYZ_Rank2_Int64, & + & VTKFile_WritedataArray_XYZ_Rank2_Int32, & + & VTKFile_WritedataArray_XYZ_Rank2_Int16, & + & VTKFile_WritedataArray_XYZ_Rank2_Int8, & + & VTKFile_WritedataArray_XYZ_Rank3_Real32, & + & VTKFile_WritedataArray_XYZ_Rank3_Real64, & + & VTKFile_WritedataArray_XYZ_Rank3_Int64, & + & VTKFile_WritedataArray_XYZ_Rank3_Int32, & + & VTKFile_WritedataArray_XYZ_Rank3_Int16, & + & VTKFile_WritedataArray_XYZ_Rank3_Int8 + + ! IO: + ! @dataArrayAppendedMethods PROCEDURE, PASS(obj) :: & - & VTKFile_WriteDataArray_Appended, & + & VTKFile_WritedataArray_Appended, & & VTKFile_WriteToScratch1, & & VTKFile_WriteToScratch2, & & VTKFile_WriteToScratch3, & @@ -272,9 +274,9 @@ MODULE VTKFile_Class & VTKFile_WriteToScratch20, & & VTKFile_WriteToScratch21, & & VTKFile_WriteToScratch22 - !! - GENERIC, PUBLIC :: WriteDataArray => VTKFile_WriteDataArray_Appended - !! + + GENERIC, PUBLIC :: WritedataArray => VTKFile_WritedataArray_Appended + GENERIC :: WriteToScratch => & & VTKFile_WriteToScratch1, & & VTKFile_WriteToScratch2, & @@ -298,19 +300,17 @@ MODULE VTKFile_Class & VTKFile_WriteToScratch20, & & VTKFile_WriteToScratch21, & & VTKFile_WriteToScratch22 - !! - !!@FieldDataMethods - !! - GENERIC, PUBLIC :: WriteFieldData => & - & VTKFile_WriteFieldData_1, & - & VTKFile_WriteFieldData_2 - !! - PROCEDURE, PASS(obj) :: & - & VTKFile_WriteFieldData_1, & - & VTKFile_WriteFieldData_2 - !! - !! @PointsMethods - !! + + ! IO: + !@FielddataMethods + GENERIC, PUBLIC :: WriteFielddata => VTKFile_WriteFielddata_1, & + & VTKFile_WriteFielddata_2 + + PROCEDURE, PASS(obj) :: VTKFile_WriteFielddata_1, & + & VTKFile_WriteFielddata_2 + + ! IO: + ! @PointsMethods GENERIC, PUBLIC :: WritePoints => & & VTKFile_WritePoints_1, & & VTKFile_WritePoints_2, & @@ -318,7 +318,7 @@ MODULE VTKFile_Class & VTKFile_WritePoints_4, & & VTKFile_WritePoints_5, & & VTKFile_WritePoints_6 - !! + PROCEDURE, PASS(obj) :: & & VTKFile_WritePoints_1, & & VTKFile_WritePoints_2, & @@ -326,27 +326,25 @@ MODULE VTKFile_Class & VTKFile_WritePoints_4, & & VTKFile_WritePoints_5, & & VTKFile_WritePoints_6 - !! - !! @PieceMethods - !! + + ! IO: + ! @PieceMethods GENERIC, PUBLIC :: WritePiece => & & VTKFile_WritePiece_1, & & VTKFile_WritePiece_2, & & VTKFile_WritePiece_3, & & VTKFile_WritePiece_4 - !! + PROCEDURE, PASS(obj) :: & & VTKFile_WritePiece_1, & & VTKFile_WritePiece_2, & & VTKFile_WritePiece_3, & & VTKFile_WritePiece_4 - !! + ! PROCEDURE, PUBLIC, PASS( obj ) :: WriteConnectivity ! PROCEDURE, PUBLIC, PASS( obj ) :: WriteGeo END TYPE VTKFile_ -PUBLIC :: VTKFile_ - !---------------------------------------------------------------------------- ! VTKFilePointer_ !---------------------------------------------------------------------------- @@ -355,21 +353,1560 @@ MODULE VTKFile_Class CLASS(VTKFile_), POINTER :: ptr => NULL() END TYPE VTKFilePointer_ -PUBLIC :: VTKFilePointer_ +!---------------------------------------------------------------------------- +! VTKFile@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: This function returns an instance of VTKFile +! +!# Introduction +! This function returns an instance if VTKFile. After calling this function +! This routine initiates the XMLFile, and opens it. +! It also write header file and dataStructure tag to the file. +! +!## Arguments: +! +! *filename*: is the name of the file +! +! *mode* : can be `READ`, `WRITE`, `NEW`, `OVERWRITE`. It is like action. +! +! *dataFormat* : defines the format of dataArray in VTKFile, it can be one fo +! the following: +! +! - `VTK_ASCII` +! - `VTK_BINARY` +! - `VTK_APPENED` +! - `VTK_RAW_APPENED`, +! - `VTK_BINARY_APPENDED`. +! - `VTK_APPENDED` and `VTK_RAW_APPENDED` are the same, where appended data +! is in raw format +! - `VTK_BINARY_APPENDED`, on the other hand, appends data in binary form +! +! *dataStructureType* : The type of vtk file. It can have following values +! +! - Imagedata, +! - RectilinearGrid, +! - StructuredGrid, +! - Polydata, +! - UnstructuredGrid +! - PImagedata +! - PRectilinearGrid +! - PStructuredGrid +! - PPolydata +! - PUnstructuredGrid +! +! *WholeExtent* : is [x1, x2, y1, y2, z1, z2], it is required for structured +! data set. +! +! *isVolatile* : It is True if volatileBuffer is used to keep the xml file +! +! *meshdataFormat* It can be Float32, Float64 + +INTERFACE + MODULE SUBROUTINE InitiateVTKFile(obj, filename, mode, dataFormat, & + & dataStructureType, WholeExtent, isVolatile, meshdataFormat, & + & Spacing, Origin) + CLASS(VTKFile_), 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 + !! VTK_ASCII, VTK_APPENEDED, VTK_BINARY + !! DEFAULT is VTK_BINARY_APPENDED + INTEGER(I4B), OPTIONAL, INTENT(IN) :: dataStructureType + !! VTK_IMAGEdata, VTK_STRUCTUREDGRID, etc. + !! Default is VTK_UnstructuredGrid + INTEGER(I4B), OPTIONAL, INTENT(IN) :: WholeExtent(:) + !! Required for structured data set + !! [x1, x2, y1, y2, z1, z2] + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isVolatile + !! True if volatileBuffer is used to keep the xml file + CHARACTER(*), OPTIONAL, INTENT(IN) :: meshdataFormat + !! Float32, Float64, etc + INTEGER(I4B), OPTIONAL, INTENT(IN) :: SPACING(:) + !! dx, dy, dz, needed in case of Imagedata + INTEGER(I4B), OPTIONAL, INTENT(IN) :: Origin(:) + !! x0, y0, z0, needed in case of Imagedata + END SUBROUTINE InitiateVTKFile +END INTERFACE + +!---------------------------------------------------------------------------- +! Deallocate@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Deallocates the content of VTKFile and close or delete it. + +INTERFACE + MODULE SUBROUTINE VTKFile_Deallocate(obj, delete) + CLASS(VTKFile_), INTENT(INOUT) :: obj + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: delete + END SUBROUTINE VTKFile_Deallocate +END INTERFACE !---------------------------------------------------------------------------- +! Final@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Finalizer for VTKFile + +INTERFACE + MODULE SUBROUTINE VTKFile_Final(obj) + TYPE(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_Final +END INTERFACE + +!---------------------------------------------------------------------------- +! UpdateOffset@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 7 July 2022 +! summary: Update the offset in VTKFile ! +!# Introduction +! +! If the dataformat is VTK_APPENDED then update the offset by number of +! bytes `nByte` + +INTERFACE + MODULE ELEMENTAL SUBROUTINE VTKFile_UpdateOffset(obj, nByte) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: nByte + END SUBROUTINE VTKFile_UpdateOffset +END INTERFACE + +!---------------------------------------------------------------------------- +! Close@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Close the file + +INTERFACE + MODULE SUBROUTINE VTKFile_Close(obj) + CLASS(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_Close +END INTERFACE + +!---------------------------------------------------------------------------- +! OpenScratchFile@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 7 July 2022 +! summary: Open the scratch file if data format is `VTK_APPENDED` + +INTERFACE + MODULE SUBROUTINE VTKFile_OpenScratchFile(obj) + CLASS(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_OpenScratchFile +END INTERFACE + +!---------------------------------------------------------------------------- +! CloseScratchFile@ConstructorMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 7 July 2022 +! summary: Close the scratch file + +INTERFACE + MODULE SUBROUTINE VTKFile_CloseScratchFile(obj) + CLASS(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_CloseScratchFile +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteRootTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 7 July 2022 +! summary: Write the root tag +! +!# Introduction +! +! This routine write the root tag. This routine is called when we initiate +! the VTKFile. following information is written. Also indent is set to 2. +! +!```xml +! +! +!``` + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteRootTag(obj) + CLASS(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_WriteRootTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataStructureTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 7 July 2022 +! summary: Write the data structure tags + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataStructureTag(obj, meshdataFormat) + CLASS(VTKFile_), INTENT(INOUT) :: obj + CHARACTER(*), OPTIONAL, INTENT(IN) :: meshdataFormat + !! Float32, Float64 + !! It should be present for parallel data structure + !! PARALLEL_VTK_RECTILINEARGRID, PARALLEL_VTK_STRUCTUREDGRID, + !! PARALLEL_VTK_UNSTRUCTUREDGRID + END SUBROUTINE VTKFile_WritedataStructureTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteStartTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Write the start tag + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteStartTag(obj, name, attrNames, attrValues) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + TYPE(String), OPTIONAL, INTENT(IN) :: attrNames(:) + TYPE(String), OPTIONAL, INTENT(IN) :: attrValues(:) + END SUBROUTINE VTKFile_WriteStartTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteEndTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Write the End tag + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteEndTag(obj, name) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + END SUBROUTINE VTKFile_WriteEndTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteSelfClosingTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Write the self closing tag + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteSelfClosingTag(obj, name, attrNames, & + & attrValues) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + TYPE(String), OPTIONAL, INTENT(IN) :: attrNames(:) + TYPE(String), OPTIONAL, INTENT(IN) :: attrValues(:) + END SUBROUTINE VTKFile_WriteSelfClosingTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteTag@TagsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: Write Tags and contents + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteTag(obj, name, attrNames, & + & attrValues, content) + CLASS(VTKFile_), 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 VTKFile_WriteTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteVerts@WriteVertMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 sept 2021 +! summary: Write Vertices + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteVerts(obj, connectivity, offsets) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: connectivity(:) + INTEGER(I4B), INTENT(IN) :: offsets(:) + END SUBROUTINE VTKFile_WriteVerts +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteCells@CellMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 sept 2021 +! summary: Write Cells + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteCells(obj, connectivity, offsets, types) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: connectivity(:) + INTEGER(I4B), INTENT(IN) :: offsets(:) + INTEGER(INT8), INTENT(IN) :: types(:) + END SUBROUTINE VTKFile_WriteCells +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArrayLocationTag@dataArrayMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: WritedataArrayLocation CELL or NODE +! +!# Introduction +! +! Write Pointdata or Celldata open/close tag. +! +!@note +! This routine must be called before saving the data related to geometric +! mesh, this function initializes the saving of data variables indicating +! the *location* (node or cell centered) of variables that will be saved. +!@endnote +! +!@note +! A single file can contain both cell and node centered variables. +!@endnote +! + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArrayLocationTag(obj, location, action) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: location + !! "CELL" and "NODE" + TYPE(String), INTENT(IN) :: action + !! "OPEN" or "CLOSE" + END SUBROUTINE VTKFile_WritedataArrayLocationTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArrayTag@dataArrayMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 13 Sept 2021 +! summary: WritedataArrayTag + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArrayTag(obj, dataType, name, & + & numberOfComponents, content, isTuples, isOffset) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: dataType + TYPE(String), INTENT(IN) :: name + INTEGER(I4B), INTENT(IN) :: numberOfComponents + TYPE(String), OPTIONAL, INTENT(IN) :: content + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isOffset + END SUBROUTINE VTKFile_WritedataArrayTag +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: This routine writes Rank1 array of Real32 +! +!# Introduction +! +! This routine writes Rank 1 of Real32. This routine calls `WritedataArrayTag` + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank1_Real32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + !! number of components in the data, default is 1 + END SUBROUTINE VTKFile_WritedataArray_Rank1_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: This routine writes Rank1 array of Real64 + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank1_Real64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank1_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: This routine writes Rank1 array of Int8 + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank1_Int8(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank1_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: This routine writes Rank1 array of Int16 + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank1_Int16(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank1_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank1_Int32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank1_Int32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank1_Int64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank1_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank2_Real32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank2_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank2_Real64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank2_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank2_Int8(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank2_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank2_Int16(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank2_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank2_Int32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank2_Int32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank2_Int64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank2_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank3_Real32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank3_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank3_Real64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank3_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank3_Int8(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank3_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank3_Int16(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank3_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank3_Int32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank3_Int32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank3_Int64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank3_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank4_Real32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:, 1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank4_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank4_Real64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:, 1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank4_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank4_Int8(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:, 1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank4_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank4_Int16(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:, 1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank4_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank4_Int32(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:, 1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank4_Int32 +END INTERFACE + !---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Rank4_Int64(obj, name, x, & + & isTuples, numberOfComponents) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:, 1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + INTEGER(I4B), OPTIONAL, INTENT(IN) :: numberOfComponents + END SUBROUTINE VTKFile_WritedataArray_Rank4_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Real32(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:) + REAL(REAL32), INTENT(IN) :: y(1:) + REAL(REAL32), INTENT(IN) :: z(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Real64(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:) + REAL(REAL64), INTENT(IN) :: y(1:) + REAL(REAL64), INTENT(IN) :: z(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int8(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:) + INTEGER(INT8), INTENT(IN) :: y(1:) + INTEGER(INT8), INTENT(IN) :: z(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int16(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:) + INTEGER(INT16), INTENT(IN) :: y(1:) + INTEGER(INT16), INTENT(IN) :: z(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int32(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:) + INTEGER(INT32), INTENT(IN) :: y(1:) + INTEGER(INT32), INTENT(IN) :: z(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int64(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:) + INTEGER(INT64), INTENT(IN) :: y(1:) + INTEGER(INT64), INTENT(IN) :: z(1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank1_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Real32(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:, 1:) + REAL(REAL32), INTENT(IN) :: y(1:, 1:) + REAL(REAL32), INTENT(IN) :: z(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Real64(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:, 1:) + REAL(REAL64), INTENT(IN) :: y(1:, 1:) + REAL(REAL64), INTENT(IN) :: z(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int8(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:, 1:) + INTEGER(INT8), INTENT(IN) :: y(1:, 1:) + INTEGER(INT8), INTENT(IN) :: z(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int16(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:, 1:) + INTEGER(INT16), INTENT(IN) :: y(1:, 1:) + INTEGER(INT16), INTENT(IN) :: z(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int32(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:, 1:) + INTEGER(INT32), INTENT(IN) :: y(1:, 1:) + INTEGER(INT32), INTENT(IN) :: z(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int64(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:, 1:) + INTEGER(INT64), INTENT(IN) :: y(1:, 1:) + INTEGER(INT64), INTENT(IN) :: z(1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank2_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Real32(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL32), INTENT(IN) :: x(1:, 1:, 1:) + REAL(REAL32), INTENT(IN) :: y(1:, 1:, 1:) + REAL(REAL32), INTENT(IN) :: z(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Real32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Real64(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + REAL(REAL64), INTENT(IN) :: x(1:, 1:, 1:) + REAL(REAL64), INTENT(IN) :: y(1:, 1:, 1:) + REAL(REAL64), INTENT(IN) :: z(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Real64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int8(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT8), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT8), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT8), INTENT(IN) :: z(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int16(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT16), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT16), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT16), INTENT(IN) :: z(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int32(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT32), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT32), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT32), INTENT(IN) :: z(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int32 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int64(obj, name, x, & + & y, z, isTuples) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + INTEGER(INT64), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT64), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT64), INTENT(IN) :: z(1:, 1:, 1:) + LOGICAL(LGT), OPTIONAL, INTENT(IN) :: isTuples + END SUBROUTINE VTKFile_WritedataArray_XYZ_Rank3_Int64 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritedataArray@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WritedataArray_Appended(obj) + CLASS(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_WritedataArray_Appended +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch1(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + CLASS(*), INTENT(IN) :: x(1:) + END SUBROUTINE VTKFile_WriteToScratch1 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch2(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + CLASS(*), INTENT(IN) :: x(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch2 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch3(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + CLASS(*), INTENT(IN) :: x(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch3 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch4(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + CLASS(*), INTENT(IN) :: x(1:, 1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch4 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch5(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(1:) + REAL(REAL64), INTENT(IN) :: y(1:) + REAL(REAL64), INTENT(IN) :: z(1:) + END SUBROUTINE VTKFile_WriteToScratch5 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch6(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(1:) + REAL(REAL32), INTENT(IN) :: y(1:) + REAL(REAL32), INTENT(IN) :: z(1:) + END SUBROUTINE VTKFile_WriteToScratch6 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch7(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT64), INTENT(IN) :: x(1:) + INTEGER(INT64), INTENT(IN) :: y(1:) + INTEGER(INT64), INTENT(IN) :: z(1:) + END SUBROUTINE VTKFile_WriteToScratch7 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch8(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT32), INTENT(IN) :: x(1:) + INTEGER(INT32), INTENT(IN) :: y(1:) + INTEGER(INT32), INTENT(IN) :: z(1:) + END SUBROUTINE VTKFile_WriteToScratch8 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch9(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT16), INTENT(IN) :: x(1:) + INTEGER(INT16), INTENT(IN) :: y(1:) + INTEGER(INT16), INTENT(IN) :: z(1:) + END SUBROUTINE VTKFile_WriteToScratch9 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch10(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT8), INTENT(IN) :: x(1:) + INTEGER(INT8), INTENT(IN) :: y(1:) + INTEGER(INT8), INTENT(IN) :: z(1:) + END SUBROUTINE VTKFile_WriteToScratch10 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch11(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(1:, 1:) + REAL(REAL64), INTENT(IN) :: y(1:, 1:) + REAL(REAL64), INTENT(IN) :: z(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch11 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch12(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(1:, 1:) + REAL(REAL32), INTENT(IN) :: y(1:, 1:) + REAL(REAL32), INTENT(IN) :: z(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch12 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch13(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT64), INTENT(IN) :: x(1:, 1:) + INTEGER(INT64), INTENT(IN) :: y(1:, 1:) + INTEGER(INT64), INTENT(IN) :: z(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch13 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch14(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT32), INTENT(IN) :: x(1:, 1:) + INTEGER(INT32), INTENT(IN) :: y(1:, 1:) + INTEGER(INT32), INTENT(IN) :: z(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch14 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch15(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT16), INTENT(IN) :: x(1:, 1:) + INTEGER(INT16), INTENT(IN) :: y(1:, 1:) + INTEGER(INT16), INTENT(IN) :: z(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch15 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch16(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT8), INTENT(IN) :: x(1:, 1:) + INTEGER(INT8), INTENT(IN) :: y(1:, 1:) + INTEGER(INT8), INTENT(IN) :: z(1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch16 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch17(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(1:, 1:, 1:) + REAL(REAL64), INTENT(IN) :: y(1:, 1:, 1:) + REAL(REAL64), INTENT(IN) :: z(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch17 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch18(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(1:, 1:, 1:) + REAL(REAL32), INTENT(IN) :: y(1:, 1:, 1:) + REAL(REAL32), INTENT(IN) :: z(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch18 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch19(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT64), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT64), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT64), INTENT(IN) :: z(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch19 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch20(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT32), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT32), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT32), INTENT(IN) :: z(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch20 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch21(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT16), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT16), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT16), INTENT(IN) :: z(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch21 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteToScratch@dataArrayAppendedMethods +!---------------------------------------------------------------------------- + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteToScratch22(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(INT8), INTENT(IN) :: x(1:, 1:, 1:) + INTEGER(INT8), INTENT(IN) :: y(1:, 1:, 1:) + INTEGER(INT8), INTENT(IN) :: z(1:, 1:, 1:) + END SUBROUTINE VTKFile_WriteToScratch22 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteFielddata@FielddataMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write Field data + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteFielddata_1(obj, name, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: name + CLASS(*), INTENT(IN) :: x + END SUBROUTINE VTKFile_WriteFielddata_1 +END INTERFACE + +!---------------------------------------------------------------------------- +! WriteFielddata@FielddataMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write Field data + +INTERFACE + MODULE SUBROUTINE VTKFile_WriteFielddata_2(obj, action) + CLASS(VTKFile_), INTENT(INOUT) :: obj + TYPE(String), INTENT(IN) :: action + !! Open, Close + END SUBROUTINE VTKFile_WriteFielddata_2 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePiece@PieceMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: WritePiece + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePiece_1(obj, extent, srcFileName) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: extent(:) + CHARACTER(*), OPTIONAL, INTENT(IN) :: srcFileName + END SUBROUTINE VTKFile_WritePiece_1 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePiece@PieceMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write Piece + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePiece_2(obj, nPoints, nCells) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: nPoints + INTEGER(I4B), INTENT(IN) :: nCells + END SUBROUTINE VTKFile_WritePiece_2 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePiece@PieceMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write Piece + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePiece_3(obj, nPoints, nVerts, nLines, & + & nStrips, nPolys) + CLASS(VTKFile_), INTENT(INOUT) :: obj + INTEGER(I4B), INTENT(IN) :: nPoints + INTEGER(I4B), INTENT(IN) :: nVerts + INTEGER(I4B), INTENT(IN) :: nLines + INTEGER(I4B), INTENT(IN) :: nStrips + INTEGER(I4B), INTENT(IN) :: nPolys + END SUBROUTINE VTKFile_WritePiece_3 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePiece@PieceMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write piece + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePiece_4(obj) + CLASS(VTKFile_), INTENT(INOUT) :: obj + END SUBROUTINE VTKFile_WritePiece_4 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write Points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_1(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(:) + REAL(REAL64), INTENT(IN) :: y(:) + REAL(REAL64), INTENT(IN) :: z(:) + END SUBROUTINE VTKFile_WritePoints_1 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_2(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(:) + REAL(REAL32), INTENT(IN) :: y(:) + REAL(REAL32), INTENT(IN) :: z(:) + END SUBROUTINE VTKFile_WritePoints_2 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_3(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(1:, 1:) + END SUBROUTINE VTKFile_WritePoints_3 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_4(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(1:, 1:) + END SUBROUTINE VTKFile_WritePoints_4 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_5(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(:, :, :) + REAL(REAL64), INTENT(IN) :: y(:, :, :) + REAL(REAL64), INTENT(IN) :: z(:, :, :) + END SUBROUTINE VTKFile_WritePoints_5 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_6(obj, x, y, z) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(:, :, :) + REAL(REAL32), INTENT(IN) :: y(:, :, :) + REAL(REAL32), INTENT(IN) :: z(:, :, :) + END SUBROUTINE VTKFile_WritePoints_6 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points + +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_7(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL64), INTENT(IN) :: x(:, :, :, :) + END SUBROUTINE VTKFile_WritePoints_7 +END INTERFACE + +!---------------------------------------------------------------------------- +! WritePoints@PointsMethods +!---------------------------------------------------------------------------- + +!> authors: Vikas Sharma, Ph. D. +! date: 15 Sept 2021 +! summary: Write points -#include "./ConstructorMethods.inc" -#include "./TagMethods.inc" -#include "./VertMethods.inc" -#include "./CellMethods.inc" -#include "./DataArrayMethods.inc" -#include "./DataArrayAppendedMethods.inc" -#include "./FieldDataMethods.inc" -#include "./PointsMethods.inc" -#include "./PieceMethods.inc" +INTERFACE + MODULE SUBROUTINE VTKFile_WritePoints_8(obj, x) + CLASS(VTKFile_), INTENT(INOUT) :: obj + REAL(REAL32), INTENT(IN) :: x(:, :, :, :) + END SUBROUTINE VTKFile_WritePoints_8 +END INTERFACE !---------------------------------------------------------------------------- ! diff --git a/src/modules/VTKFile/src/VertMethods.inc b/src/modules/VTKFile/src/VertMethods.inc deleted file mode 100644 index 365254c02..000000000 --- a/src/modules/VTKFile/src/VertMethods.inc +++ /dev/null @@ -1,32 +0,0 @@ -! 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 -! - -!---------------------------------------------------------------------------- -! WriteVerts@WriteVertMethods -!---------------------------------------------------------------------------- - -!> authors: Vikas Sharma, Ph. D. -! date: 15 sept 2021 -! summary: Write Vertices - -INTERFACE -MODULE SUBROUTINE VTKFile_WriteVerts( obj, connectivity, offsets ) - CLASS( VTKFile_ ), INTENT( INOUT ) :: obj - INTEGER( I4B ), INTENT( IN ) :: connectivity( : ) - INTEGER( I4B ), INTENT( IN ) :: offsets( : ) -END SUBROUTINE VTKFile_WriteVerts -END INTERFACE diff --git a/src/submodules/MatrixField/src/MatrixField_Class@ConstructorMethods.F90 b/src/submodules/MatrixField/src/MatrixField_Class@ConstructorMethods.F90 index d1a9fd227..29b3aec8d 100644 --- a/src/submodules/MatrixField/src/MatrixField_Class@ConstructorMethods.F90 +++ b/src/submodules/MatrixField/src/MatrixField_Class@ConstructorMethods.F90 @@ -570,7 +570,7 @@ INTEGER(I4B) :: ierr CALL AbstractMatrixFieldDeallocate(obj) CALL DEALLOCATE (obj%mat) -CALL DEALLOCATE (obj%Pmat) +CALL Pmat_Deallocate(obj%Pmat) obj%isRectangle = .FALSE. END PROCEDURE mField_Deallocate diff --git a/src/submodules/VTKFile/src/VTKFile_Class@ConstructorMethods.F90 b/src/submodules/VTKFile/src/VTKFile_Class@ConstructorMethods.F90 index 544fb96ca..f7e12974d 100644 --- a/src/submodules/VTKFile/src/VTKFile_Class@ConstructorMethods.F90 +++ b/src/submodules/VTKFile/src/VTKFile_Class@ConstructorMethods.F90 @@ -25,89 +25,97 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE InitiateVTKFile -CHARACTER(*), PARAMETER :: myName = "InitiateVTKFile" -! -! main -! +CHARACTER(*), PARAMETER :: myName = "InitiateVTKFile()" + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[START] InitiateVTKFile()') +#endif + IF (obj%isInitiated) THEN - CALL e%raiseError(modName//'::'//myName//" - "// & - & ' - VTKFile is already initiated, use Deallocate() first') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: VTKFile is already initiated, '// & + & ' call Deallocate() first') + RETURN END IF -! -! -! -obj%DataFormat = DataFormat -obj%DataStructureType = DataStructureType -obj%DataStructureName = TRIM(DataStructureName(DataStructureType)) + +obj%dataFormat = Input(option=dataFormat, default=VTK_BINARY_APPENDED) +obj%dataStructureType = Input(option=dataStructureType, & + & default=VTK_UnstructuredGrid) + +obj%dataStructureName = TRIM(dataStructureName(obj%dataStructureType)) obj%WholeExtent = 0 obj%origin = 0 obj%spacing = 1 -! + IF (PRESENT(WholeExtent)) THEN obj%WholeExtent(1:SIZE(WholeExtent)) = WholeExtent(:) END IF -! + IF (PRESENT(origin)) THEN obj%origin(1:SIZE(origin)) = origin(:) END IF -! + IF (PRESENT(spacing)) THEN obj%SPACING(1:SIZE(spacing)) = SPACING(:) END IF -! + IF (PRESENT(isVolatile)) THEN obj%isVolatile = isVolatile ELSE obj%isVolatile = .FALSE. END IF -! -SELECT CASE (DataStructureType) - ! - ! Structured case - ! -CASE (VTK_ImageData, VTK_RectilinearGrid, VTK_StructuredGrid, & - & PARALLEL_VTK_ImageData, PARALLEL_VTK_RectilinearGrid, & + +SELECT CASE (obj%dataStructureType) + +! Structured case +CASE (VTK_Imagedata, VTK_RectilinearGrid, VTK_StructuredGrid, & + & PARALLEL_VTK_Imagedata, PARALLEL_VTK_RectilinearGrid, & & PARALLEL_VTK_StructuredGrid) obj%isStructured = .TRUE. - ! + IF (.NOT. PRESENT(WholeExtent)) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & ' - In case of structured data set WholeExtent should be given') - ! + ! Unstructured case - ! -CASE (VTK_PolyData, VTK_UnstructuredGrid, PARALLEL_VTK_PolyData, & +CASE (VTK_Polydata, VTK_UnstructuredGrid, PARALLEL_VTK_Polydata, & & PARALLEL_VTK_UnstructuredGrid) obj%isStructured = .FALSE. - ! + ! Default case prints error - ! CASE DEFAULT - CALL e%raiseError(modName//'::'//myName//" - "// & - & ' - Cannot recognize DataStructureType') + CALL e%RaiseError(modName//'::'//myName//" - "// & + & '[INTERNAL ERROR] :: Cannot recognize dataStructureType') + RETURN END SELECT -! + ! Handle appended case -! -IF (DataFormat .EQ. VTK_APPENDED) THEN +IF (obj%dataFormat .EQ. VTK_APPENDED) THEN obj%encoding4Appended = 'raw' obj%offset = 0 -ELSE IF (DataFormat .EQ. VTK_BINARY_APPENDED) THEN +ELSE IF (obj%dataFormat .EQ. VTK_BINARY_APPENDED) THEN obj%encoding4Appended = 'base64' - obj%DataFormat = VTK_APPENDED + obj%dataFormat = VTK_APPENDED obj%offset = 0 END IF -! + IF (obj%isVolatile) THEN obj%volatileBuffer = '' ELSE - CALL obj%initiate(filename=filename, mode=mode) + CALL obj%Initiate(filename=filename, & + & mode=Input(option=mode, default="NEW")) CALL obj%OPEN() END IF -! + CALL obj%WriteRootTag() -CALL obj%WriteDataStructureTag(meshDataFormat=meshDataFormat) +CALL obj%WritedataStructureTag(meshdataFormat=meshdataFormat) CALL obj%OpenScratchFile() + +#ifdef DEBUG_VER +CALL e%RaiseInformation(modName//'::'//myName//' - '// & + & '[END] InitiateVTKFile()') +#endif END PROCEDURE InitiateVTKFile !---------------------------------------------------------------------------- @@ -117,9 +125,9 @@ MODULE PROCEDURE VTKFile_Deallocate CALL xmlFile_Deallocate(obj, delete) obj%isStructured = .FALSE. -obj%DataStructureType = 0 -obj%DataStructureName = '' -obj%DataFormat = 0 +obj%dataStructureType = 0 +obj%dataStructureName = '' +obj%dataFormat = 0 obj%WholeExtent = 0 obj%indent = 0 obj%offset = 0 @@ -146,8 +154,8 @@ MODULE PROCEDURE VTKFile_Close IF (obj%isOpen()) THEN - CALL obj%WriteEndTag(name=String(obj%DataStructureName)) - CALL obj%WriteDataArray() + CALL obj%WriteEndTag(name=String(obj%dataStructureName)) + CALL obj%WritedataArray() CALL obj%WriteEndTag(name=String('VTKFile')) IF (.NOT. obj%isVolatile) CALL xmlFile_Close(obj) CALL obj%closeScratchFile() @@ -159,7 +167,7 @@ !---------------------------------------------------------------------------- MODULE PROCEDURE VTKFile_UpdateOffset -IF (obj%DataFormat .EQ. VTK_APPENDED) THEN +IF (obj%dataFormat .EQ. VTK_APPENDED) THEN IF (obj%encoding4Appended .EQ. 'raw') THEN obj%offset = obj%offset + BYInt32 + nByte ELSE @@ -176,7 +184,7 @@ CHARACTER(*), PARAMETER :: myName = "VTKFile_OpenScratchFile" INTEGER(I4B) :: iostat ! -IF (obj%DataFormat .EQ. VTK_APPENDED) THEN +IF (obj%dataFormat .EQ. VTK_APPENDED) THEN ! obj%scratch = getUnitNo() OPEN (newunit=obj%scratch, & & form='UNFORMATTED', & @@ -186,7 +194,7 @@ & iostat=iostat) ! IF (iostat .NE. 0) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & ' - Some error has occured while opening scratch file') END IF ! @@ -200,10 +208,10 @@ INTEGER(I4B) :: iostat CHARACTER(*), PARAMETER :: myName = "VTKFile_CloseScratchFile" ! -IF (obj%DataFormat .EQ. VTK_APPENDED) THEN +IF (obj%dataFormat .EQ. VTK_APPENDED) THEN CLOSE (unit=obj%scratch, iostat=iostat) IF (iostat .NE. 0) & - & CALL e%raiseError(modName//'::'//myName//" - "// & + & CALL e%RaiseError(modName//'::'//myName//" - "// & & ' - Some error has occured while closing scratch file') END IF END PROCEDURE VTKFile_CloseScratchFile