!/*****************************************************************************/1! *2! * Elmer/Ice, a glaciological add-on to Elmer3! * http://elmerice.elmerfem.org4! *5! *6! * This program is free software; you can redistribute it and/or7! * modify it under the terms of the GNU General Public License8! * as published by the Free Software Foundation; either version 29! * of the License, or (at your option) any later version.10! *11! * This program is distributed in the hope that it will be useful,12! * but WITHOUT ANY WARRANTY; without even the implied warranty of13! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14! * GNU General Public License for more details.15! *16! * You should have received a copy of the GNU General Public License17! * along with this program (in file fem/GPL-2); if not, write to the18! * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,19! * Boston, MA 02110-1301, USA.20! *21! *****************************************************************************/22! ******************************************************************************23! *24! * Authors: Mondher Chekki25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date: 15/12/201829!30! ****************************************************************************/31! -----------------------------------------------------------------------3233MODULE ElmerIceUtils3435USE DefUtils3637CONTAINS3839SUBROUTINE ComputeWeight(Model, Solver, VarName, WeightIn)4041!------------------------------------------------------------------------------42!******************************************************************************43!44! Compute weight at Boundaries (if Weight is not associated)45! and Sum over all Partitions46!47! ARGUMENTS:48!49! TYPE(Model_t) :: Model,50! INPUT: All model information (mesh,materials,BCs,etc...)51!52! TYPE(Solver_t) :: Solver53! INPUT: Linear equation solver options54!55! CHARACTER(LEN=MAX_NAME_LEN) :: VarName56! INPUT: Name of the variable57!58! TYPE(Variable_t) :: WeightIn59! INPUT/OUTPUT : Variable Associated Weight60!61!******************************************************************************62IMPLICIT NONE6364TYPE(Model_t) :: Model65TYPE(Solver_t), TARGET :: Solver66CHARACTER(LEN=MAX_NAME_LEN) :: VarName67TYPE(Variable_t), POINTER :: WeightIn6869!------------------------------------------------------------------------------70! Local variables71!------------------------------------------------------------------------------72CHARACTER(LEN=MAX_NAME_LEN) :: FunctionName7374LOGICAL :: UnFoundFatal=.TRUE.75INTEGER :: nlen76REAL(KIND=dp) :: at, at07778FunctionName='ComputeWeight'7980!------------------------------------------------------------------------------81! Compute Boundary Weights82!------------------------------------------------------------------------------83nlen = LEN_TRIM(VarName)8485NULLIFY( WeightIn )8687CALL CalculateNodalWeights(Model % Solver,.TRUE.)88WeightIn => VariableGet( Solver % Mesh % Variables, &89VarName(1:nlen)//' Boundary Weights' ,UnFoundFatal=UnFoundFatal)90IF( .NOT. ASSOCIATED( WeightIn ) ) THEN91CALL Fatal('ComputeWeight','Weight variable not present?')92END IF9394CALL INFO(FunctionName, 'All Done', level=3)9596END SUBROUTINE ComputeWeight9798SUBROUTINE UpdatePartitionWeight(Model, Solver, VarName, Force, Force_tmp)99100!------------------------------------------------------------------------------101!******************************************************************************102!103! Compute weight at Boundaries (if Weight is not associated)104! and Sum over all Partitions105!106! ARGUMENTS:107!108! TYPE(Model_t) :: Model,109! INPUT: All model information (mesh,materials,BCs,etc...)110!111! TYPE(Solver_t) :: Solver112! INPUT: Linear equation solver options113!114! CHARACTER(LEN=MAX_NAME_LEN) :: VarName115! INPUT: Name of the variable116!117! TYPE(Variable_t) :: WeightIn118! INPUT/OUTPUT : Variable Associated Weight119!120!******************************************************************************121IMPLICIT NONE122123TYPE(Model_t) :: Model124TYPE(Solver_t), TARGET :: Solver125CHARACTER(LEN=MAX_NAME_LEN) :: VarName126TYPE(Variable_t), POINTER :: Force127REAL(KIND=dp) :: Force_tmp(:)128129130INTEGER, POINTER :: WeightPerm(:), ForcePerm(:)131INTEGER :: i, nlen, istat132REAL(KIND=dp), POINTER :: WeightValues(:), ForceValues(:)133REAL(KIND=dp) , ALLOCATABLE :: WeightValues_tmp(:)134TYPE(Variable_t), POINTER :: WeightIn135136!------------------------------------------------------------------------------137! Local variables138!------------------------------------------------------------------------------139CHARACTER(LEN=MAX_NAME_LEN) :: FunctionName140141LOGICAL :: UnFoundFatal=.TRUE.142REAL(KIND=dp) :: at, at0143144FunctionName='UpdatePartitionWeight'145146CALL ComputeWeight(Model, Solver, VarName, WeightIn)147148WeightPerm => WeightIn % Perm149WeightValues => WeightIn % Values150151ForcePerm => Force % Perm152ForceValues => Force % Values153154!----- -------------------------------------------------------------------------155! Allocate temporary storage156!----- -------------------------------------------------------------------------157158ALLOCATE(WeightValues_tmp(SIZE(WeightValues)),STAT=istat)159IF ( istat /= 0 ) THEN160CALL Fatal( FunctionName, 'Memory allocation error.' )161END IF162163WeightValues_tmp(:) = WeightValues(:)164Force_tmp(:) = ForceValues(:)165166IF ( ParEnv % PEs >1 ) THEN167CALL ParallelSumVector( Solver % Matrix, WeightValues)168DO i=1, Model % Mesh % NumberOfNodes169IF (WeightPerm(i)>0) THEN170Force_tmp(ForcePerm(i)) = Force_tmp(ForcePerm(i)) * &171(WeightValues_tmp(WeightPerm(i))/WeightValues(WeightPerm(i)))172END IF173END DO174END IF175176CALL INFO(FunctionName, 'All Done', level=3)177178END SUBROUTINE UpdatePartitionWeight179180181SUBROUTINE UpdatePeriodicNodes(Model, Solver, VarName, WeightIn, ThisDim)182183!------------------------------------------------------------------------------184!******************************************************************************185!186! Update values at Periodic nodes187!188! ARGUMENTS:189!190! TYPE(Model_t) :: Model,191! INPUT: All model information (mesh,materials,BCs,etc...)192!193! TYPE(Solver_t) :: Solver194! INPUT: Linear equation solver options195!196! CHARACTER(LEN=MAX_NAME_LEN) :: VarName197! INPUT: Name of the variable198!199! TYPE(Variable_t) :: WeightIn200! INPUT/OUTPUT : Variable Associated Weight201!202! INTEGER :: ThisDim203! INPUT : Variable Component X/Y/Z204!205!******************************************************************************206207208IMPLICIT NONE209210TYPE(Model_t) :: Model211TYPE(Solver_t), TARGET :: Solver212CHARACTER(LEN=MAX_NAME_LEN) :: VarName213TYPE(Variable_t), POINTER :: WeightIn214INTEGER :: ThisDim215216!------------------------------------------------------------------------------217! Local variables218!------------------------------------------------------------------------------219TYPE(Variable_t), POINTER :: Weight220REAL(KIND=dp), POINTER :: WeightValues(:)221INTEGER, POINTER :: WeightPerm(:)222CHARACTER(LEN=MAX_NAME_LEN) :: FunctionName223224TYPE(Matrix_t), POINTER :: Projector225LOGICAL, ALLOCATABLE :: ActivePart(:)226227INTEGER :: iBC, ii, jj, i ,j , k, nlen, l228INTEGER :: PeriodicNode1, PeriodicNode2229INTEGER :: LocalPeriodicNode1, LocalPeriodicNode2230INTEGER :: VarDim231REAL(KIND=dp) :: isPeriodic, tmpValue232233LOGICAL :: UnFoundFatal=.TRUE., GotIt234REAL(KIND=dp) :: at, at0235236FunctionName='UpdatePeriodicNodes'237238239NULLIFY( Weight )240241Weight => WeightIn242243WeightPerm => Weight % Perm244WeightValues => Weight % Values245246nlen = LEN_TRIM(VarName)247VarDim = Weight % DOFs248249CALL INFO("Update Periodic Nodes for: "//VarName(1:nlen), 'Start', level=3)250!---------------------------------------------------------------------------251! date Values at Periodic Nodes using a Projector252!---------------------------------------------------------------------------253ALLOCATE(ActivePart(MAX( Model % NumberOfBodyForces,Model % NumberOfBCs)))254255ActivePart = .FALSE.256257DO iBC=1,Model % NumberOfBCs258IF ( ListGetLogical( Model % BCs(iBC) % Values, &259'Periodic BC ' // VarName(1:nlen), GotIt ) ) ActivePart(iBC) = .TRUE.260IF ( ListGetLogical( Model % BCs(iBC) % Values, &261'Anti Periodic BC ' // VarName(1:nlen), GotIt ) ) ActivePart(iBC) = .TRUE.262IF ( ListCheckPresent( Model % BCs(iBC) % Values, &263'Periodic BC Scale ' // VarName(1:nlen) ) ) ActivePart(iBC) = .TRUE.264END DO265266DO iBC=1,Model % NumberOfBCs267IF (ActivePart(iBC)) THEN268Projector => Model % BCs(iBC) % PMatrix269IF ( ASSOCIATED( Projector ) ) THEN270DO i=1,Projector % NumberOfRows271DO l = Projector % Rows(i), Projector % Rows(i+1)-1272273PeriodicNode1 = Projector % InvPerm(i)274PeriodicNode2 = Projector % Cols(l)275isPeriodic = Projector % Values(l)276277IF ( PeriodicNode1 <= 0 .OR. PeriodicNode2 <= 0 ) CYCLE278279LocalPeriodicNode1 = WeightPerm(PeriodicNode1)280LocalPeriodicNode2 = WeightPerm(PeriodicNode2)281282IF ( LocalPeriodicNode1>0 .and. LocalPeriodicNode2>0 ) THEN283284LocalPeriodicNode1=VarDim*(LocalPeriodicNode1-1)+ThisDim285LocalPeriodicNode2=VarDim*(LocalPeriodicNode2-1)+ThisDim286287tmpValue=WeightValues(LocalPeriodicNode1)288289WeightValues(LocalPeriodicNode1) = tmpValue + isPeriodic*WeightValues(LocalPeriodicNode2)290WeightValues(LocalPeriodicNode2) = WeightValues(LocalPeriodicNode2) + isPeriodic*tmpValue291292ENDIF !LocalPeriodicNode >0293END DO !l294END DO !i295END IF !Projector296END IF !ActivePart297298END DO !iBC299300CALL INFO(FunctionName, 'All Done', level=3)301302END SUBROUTINE UpdatePeriodicNodes303304SUBROUTINE SetZeroAtPeriodicNodes(Model, Solver, VarName, WeightValues, WeightPerm, TargetPerm)305306!------------------------------------------------------------------------------307!******************************************************************************308!309! Set 0 values at Periodic nodes310!311! ARGUMENTS:312!313! TYPE(Model_t) :: Model,314! INPUT: All model information (mesh,materials,BCs,etc...)315!316! TYPE(Solver_t) :: Solver317! INPUT: Linear equation solver options318!319! CHARACTER(LEN=MAX_NAME_LEN) :: VarName320! INPUT: Name of the variable321!322!******************************************************************************323324325IMPLICIT NONE326327TYPE(Model_t) :: Model328TYPE(Solver_t), TARGET :: Solver329CHARACTER(LEN=MAX_NAME_LEN) :: VarName330REAL(KIND=dp) :: WeightValues(:)331INTEGER :: WeightPerm(:)332INTEGER :: TargetPerm(:)333334!------------------------------------------------------------------------------335! Local variables336!------------------------------------------------------------------------------337TYPE(Variable_t), POINTER :: Weight338CHARACTER(LEN=MAX_NAME_LEN) :: FunctionName339340TYPE(Matrix_t), POINTER :: Projector341LOGICAL, ALLOCATABLE :: ActivePart(:)342343INTEGER :: iBC, ii, jj, i ,j , k, nlen, l344INTEGER :: PeriodicNode1345INTEGER :: LocalPeriodicNode1346REAL(KIND=dp) :: isPeriodic347348LOGICAL :: GotIt349REAL(KIND=dp) :: at, at0350351FunctionName='SetZeroAtPeriodicNodes'352353nlen = LEN_TRIM(VarName)354!---------------------------------------------------------------------------355! date Values at Periodic Nodes using a Projector356!---------------------------------------------------------------------------357ALLOCATE(ActivePart(MAX( Model % NumberOfBodyForces,Model % NumberOfBCs)))358359ActivePart = .FALSE.360361DO iBC=1,Model % NumberOfBCs362IF ( ListGetLogical( Model % BCs(iBC) % Values, &363'Periodic BC ' // VarName(1:nlen), GotIt ) ) ActivePart(iBC) = .TRUE.364IF ( ListGetLogical( Model % BCs(iBC) % Values, &365'Anti Periodic BC ' // VarName(1:nlen), GotIt ) ) ActivePart(iBC) = .TRUE.366IF ( ListCheckPresent( Model % BCs(iBC) % Values, &367'Periodic BC Scale ' // VarName(1:nlen) ) ) ActivePart(iBC) = .TRUE.368END DO369370DO iBC=1,Model % NumberOfBCs371IF (ActivePart(iBC)) THEN372Projector => Model % BCs(iBC) % PMatrix373IF ( ASSOCIATED( Projector ) ) THEN374DO i=1,Projector % NumberOfRows375DO l = Projector % Rows(i), Projector % Rows(i+1)-1376377PeriodicNode1 = Projector % InvPerm(i)378379isPeriodic = Projector % Values(l)380381IF ( PeriodicNode1 <= 0 ) CYCLE382383LocalPeriodicNode1 = TargetPerm(PeriodicNode1)384385IF ( WeightPerm(PeriodicNode1) > 0 ) WeightValues(LocalPeriodicNode1) = 0.0D0386387END DO !l388END DO !i389END IF !Projector390END IF !ActivePart391392END DO !iBC393394CALL INFO(FunctionName, 'All Done', level=3)395396END SUBROUTINE SetZeroAtPeriodicNodes397398END MODULE ElmerIceUtils399400401