Path: blob/devel/elmerice/Solvers/ComputeCalvingNormal.F90
3204 views
!/*****************************************************************************/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: Olivier Gagliardini, Juha Ruokolainen25! * Email: Juha.Ruokolainen [at] csc.fi26! * Web: http://elmerice.elmerfem.org27! * Address: CSC - Scientific Computing Ltd.28! * Keilaranta 1429! * 02101 Espoo, Finland30! *31! * Original Date: 14 May 200732! *33! *****************************************************************************34!> Module containing solver for computation of surface normals3536!NB: This is just a local copy of ComputeNormalSolver, with modified keywords37! to allow proper normal computation on two adjacent boundaries.38SUBROUTINE ComputeCalvingNormalSolver( Model, Solver, dt, TransientSimulation )39!------------------------------------------------------------------------------40!******************************************************************************41!42! ARGUMENTS:43!44! TYPE(Model_t) :: Model,45! INPUT: All model information (mesh, materials, BCs, etc...)46!47! TYPE(Solver_t) :: Solver48! INPUT: Linear & nonlinear equation solver options49!50! REAL(KIND=dp) :: dt,51! INPUT: Timestep size for time dependent simulations52!53! LOGICAL :: TransientSimulation54! INPUT: Steady state or transient simulation55!56!Modification have been done to deal with problems where we don't want to compute57!the normal on all the boundaries (problem with the corners)58!59!Keywords are: ComputeAll = True/False computing / or not the normal on every boundary60! ComputeNormal = True to compute the normal on a given boundary61!******************************************************************************62USE DefUtils6364IMPLICIT NONE65!------------------------------------------------------------------------------66TYPE(Solver_t), TARGET :: Solver67TYPE(Model_t) :: Model6869REAL(KIND=dp) :: dt70LOGICAL :: TransientSimulation7172!------------------------------------------------------------------------------73! Local variables74!------------------------------------------------------------------------------75TYPE(Mesh_t), POINTER :: Mesh76TYPE(Element_t), POINTER :: Element77TYPE(Variable_t), POINTER :: NormalSolution78TYPE(ValueList_t), POINTER :: SolverParams7980INTEGER :: i, j, k, l, m, n, cnt, ierr, t, DIM81REAL(KIND=dp) :: u, v, w, s82REAL(KIND=dp), POINTER :: Nvector(:), PassNVector(:), RecvNVector(:)83INTEGER, POINTER :: Permutation(:), Neighbours(:)84INTEGER, ALLOCATABLE :: NeighbourPerm(:), PassCount(:), RecvCount(:),&85PassIndices(:,:), RecvIndices(:,:), LocalPerm(:)86INTEGER, DIMENSION(MPI_STATUS_SIZE) :: status87TYPE(Nodes_t), SAVE :: Nodes88REAL(KIND=dp) :: Bu, Bv, Normal(3)8990LOGICAL :: Found, Parallel, MeActive=.TRUE.91LOGICAL, ALLOCATABLE :: Hit(:), PartActive(:)9293CHARACTER(LEN=MAX_NAME_LEN) :: SolverName = 'ComputeCalvingNormalSolver'9495Parallel = (ParEnv % PEs > 1)96Mesh => Solver % Mesh97DIM = CoordinateSystemDimension()9899!---------------------------------------100! Setup pointer to the current solution:101!---------------------------------------102NormalSolution => Solver % Variable103IF ( ASSOCIATED( NormalSolution ) ) THEN104Nvector => NormalSolution % Values105Permutation => NormalSolution % Perm106Nvector = 0.0_dp !wipe out previous107ELSE108PRINT *,'FATAL: Unable to set pointer to the current solution'109STOP110END IF111112113CALL INFO(SolverName, 'Computing Normal Vector for Nodes', level=3)114115SolverParams => GetSolverParams()116117!Check if current partition has anything to do118IF(Parallel) THEN119MeActive = .TRUE.120IF(Solver % NumberOfActiveElements <= 0) MeActive = .FALSE.121ALLOCATE(PartActive(ParEnv % PEs))122123CALL MPI_ALLGATHER(MeActive,1,MPI_LOGICAL,&124PartActive,1,MPI_LOGICAL, ELMER_COMM_WORLD, ierr)125126IF(.NOT. MeActive) RETURN127128ALLOCATE(Hit(Mesh % NumberOfNodes), &129NeighbourPerm(ParEnv % PEs),&130PassCount(ParEnv % NumOfNeighbours),&131RecvCount(ParEnv % NumOfNeighbours),&132PassIndices(ParEnv % NumOfNeighbours, Mesh % NumberOfNodes),&133RecvIndices(ParEnv % NumOfNeighbours, Mesh % NumberOfNodes),&134LocalPerm( MAXVAL(Mesh % ParallelInfo % GlobalDOFs)))135136NeighbourPerm = 0137LocalPerm = 0138Hit = .FALSE.139RecvCount = 0140PassCount = 0141PassIndices = 0142143!Create a list of partitions with which we share nodes144cnt = 0145DO i=1,ParEnv % PEs146IF(ParEnv % MyPE == i-1) CYCLE147IF(.NOT. PartActive(i)) CYCLE148IF(.NOT. ParEnv % IsNeighbour(i)) CYCLE149cnt = cnt + 1150NeighbourPerm(i) = cnt151END DO152153!Perm to get back from global to local node numbering154DO i=1, Mesh % NumberOfNodes155LocalPerm(Mesh % ParallelInfo % GlobalDOFs(i)) = i156END DO157158END IF !Parallel159160DO t = 1, Solver % NumberOfActiveElements161Element => GetActiveElement(t)162163IF(Element % PartIndex /= ParEnv % MyPE) CYCLE164165n = GetElementNOFNodes(Element)166IF (n == 1) CYCLE167168CALL GetElementNodes( Nodes, Element )169170DO i = 1,n171j = Element % NodeIndexes( i )172k = Permutation(j)173174IF(k <= 0) CALL Fatal(SolverName, &175"Encountered invalid perm, this is a programming error")176177Bu = Element % Type % NodeU(i)178IF ( Element % Type % Dimension > 1 ) THEN179Bv = Element % Type % NodeV(i)180ELSE181Bv = 0.0D0182END IF183Normal = NormalVector(Element, Nodes, Bu, Bv, .TRUE.)184Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k) +&185Normal(1:DIM)186187IF(Parallel) Hit(j) = .TRUE.188END DO189END DO190191IF(Parallel) THEN192193!Find nodes on partition boundaries194RecvCount = 0195PassCount = 0196PassIndices = 0197DO i=1,Model % Mesh % NumberOfNodes198IF(.NOT.Hit(i)) CYCLE !no normal computation199IF(.NOT. Mesh % ParallelInfo % GInterface(i)) CYCLE !no partition interface200Neighbours => Mesh % ParallelInfo % NeighbourList(i) % Neighbours201202DO j=1,SIZE(Neighbours)203IF(Neighbours(j) == ParEnv % MyPE) CYCLE204IF(.NOT. PartActive(Neighbours(j)+1)) CYCLE205206m = NeighbourPerm(Neighbours(j)+1)207PassCount(m) = PassCount(m) + 1208PassIndices(m, PassCount(m)) = i209END DO210END DO211212!Send213DO i=1,ParEnv % PEs214IF(NeighbourPerm(i) == 0) CYCLE215m = NeighbourPerm(i)216217!Send count218CALL MPI_BSEND(PassCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, ierr)219!Send (global) node numbers220CALL MPI_BSEND(Mesh % ParallelInfo % GlobalDOFs(PassIndices(m,1:PassCount(m))),&221PassCount(m), MPI_INTEGER, i-1, 201, ELMER_COMM_WORLD, ierr)222223!Construct normal vector array to pass224ALLOCATE(PassNVector(PassCount(m) * DIM))225DO j=1, PassCount(m)226l = Permutation(PassIndices(m,j))227PassNVector(DIM*(j-1)+1:DIM*j) = NVector(DIM*(l-1)+1:DIM*l)228END DO229230!Send normal vectors231CALL MPI_BSEND(PassNVector, PassCount(m)*DIM, MPI_DOUBLE_PRECISION, &232i-1, 202, ELMER_COMM_WORLD, ierr)233234DEALLOCATE(PassNVector)235END DO236237!Receive238DO i=1,ParEnv % PEs239240IF(NeighbourPerm(i) == 0) CYCLE241m = NeighbourPerm(i)242243!Receive count244CALL MPI_RECV(RecvCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, status, ierr)245246!Receive (global) node numbers247CALL MPI_RECV(RecvIndices(m,1:RecvCount(m)), RecvCount(m), MPI_INTEGER, &248i-1, 201, ELMER_COMM_WORLD, status, ierr)249250!Receive normal vectors251ALLOCATE(RecvNVector(RecvCount(m)*DIM))252CALL MPI_RECV(RecvNVector, RecvCount(m)*DIM, MPI_DOUBLE_PRECISION, &253i-1, 202, ELMER_COMM_WORLD, status, ierr)254255DO j=1, RecvCount(m)256IF(.NOT. Hit(LocalPerm(RecvIndices(m,j)))) CYCLE !passed a halo node257k = Permutation(LocalPerm(RecvIndices(m,j)))258NVector(DIM*(k-1)+1:DIM*k) = NVector(DIM*(k-1)+1:DIM*k) + RecvNVector(DIM*(j-1)+1:DIM*j)259END DO260261DEALLOCATE(RecvNVector)262END DO263264END IF !Parallel265266DO i=1,Model % NumberOfNodes267k = Permutation(i)268IF ( k > 0 ) THEN269s = SQRT( SUM( Nvector(DIM*(k-1)+1:DIM*k)**2 ) )270271IF ( s /= 0.0D0 ) THEN272Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k)/s273END IF274END IF275276END DO277278CALL INFO(SolverName, 'End', level=3)279280!------------------------------------------------------------------------------281END SUBROUTINE ComputeCalvingNormalSolver282!------------------------------------------------------------------------------283284285