Path: blob/devel/elmerice/Solvers/FrontDisplacement.F90
3203 views
!/*****************************************************************************/1! *2! * Elmer, A Finite Element Software for Multiphysical Problems3! *4! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland5! *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! *25! * Slightly modified version of MeshSolve.F90 for computing mesh update for26! * 2D calving simulations. The main difference is that this solver stores27! * the initial model mesh (Mesh0) and computes displacements relative to this28! * mesh, to avoid the progressive mesh degeneracy associated with repeated29! * calls to Mesh Update.30! *3132!/******************************************************************************33! *34! * Authors: Juha Ruokolainen, Joe Todd35! * Email: [email protected]36! * Web: http://www.csc.fi/elmer37! * Address: CSC - IT Center for Science Ltd.38! * Keilaranta 1439! * 02101 Espoo, Finland40! *41! * Original Date: 10 May 200042! *43! *****************************************************************************/4445!------------------------------------------------------------------------------46!> Initialization for the primary solver i.e. MeshSolver.47!------------------------------------------------------------------------------48SUBROUTINE FDMeshSolver_Init( Model,Solver,dt,TransientSimulation )49!------------------------------------------------------------------------------50USE DefUtils51IMPLICIT NONE52!------------------------------------------------------------------------------53TYPE(Model_t) :: Model54TYPE(Solver_t), TARGET :: Solver55LOGICAL :: TransientSimulation56REAL(KIND=dp) :: dt57!------------------------------------------------------------------------------58TYPE(ValueList_t), POINTER :: Params59INTEGER :: dim60LOGICAL :: Found, Calculate6162Params => Solver % Values63dim = CoordinateSystemDimension()6465Calculate = ListGetLogical( Params,'Compute Front Displacement Velocity',Found )66IF(.NOT. Found ) Calculate = .TRUE.6768IF( Calculate ) THEN69IF( TransientSimulation ) THEN70IF( dim == 2 ) THEN71CALL ListAddString( Params,&72NextFreeKeyword('Exported Variable',Params),&73'-dofs 2 Front Displacement Velocity')74ELSE75CALL ListAddString( Params,&76NextFreeKeyword('Exported Variable',Params),&77'-dofs 3 Front Displacement Velocity')78END IF79END IF80END IF8182END SUBROUTINE FDMeshSolver_Init838485!------------------------------------------------------------------------------86!> Subroutine for extending displacement in mesh smoothly over87!> the domain. The intended use of the solver is in fluid-structure interaction,88!> for example. In transient cases the solver also computes the mesh velocity.89!> This is a dynamically loaded solver with a standard interface.90!> May be also loaded internally to mimic the old static implementation.91!> \ingroup Solvers9293!This has been modified by Joe Todd as a secondary mesh displacement solver for94!calving events.95!------------------------------------------------------------------------------96SUBROUTINE FDMeshSolver( Model,Solver,dt,TransientSimulation )97!------------------------------------------------------------------------------98USE DefUtils99IMPLICIT NONE100!------------------------------------------------------------------------------101TYPE(Model_t) :: Model102TYPE(Solver_t), TARGET :: Solver103LOGICAL :: TransientSimulation104REAL(KIND=dp) :: dt105!------------------------------------------------------------------------------106! Local variables107!------------------------------------------------------------------------------108INTEGER :: i,j,k,n,nd,nb,t,STDOFs,LocalNodes,istat,NoNodes109110TYPE(Element_t),POINTER :: Element111TYPE(ValueList_t),POINTER :: Material, BC112TYPE(Mesh_t),POINTER :: Mesh0 => Null()113TYPE(Nodes_t),POINTER :: Nodes0114REAL(KIND=dp) :: RelativeChange, UNorm, PrevUNorm, maxu115116TYPE(Variable_t), POINTER :: MeshSol, InitXVar, InitYVar117118REAL(KIND=dp), POINTER :: MeshUpdate(:), MeshVelocity(:)119120INTEGER, POINTER :: MeshPerm(:)121122LOGICAL :: AllocationsDone = .FALSE., Isotropic = .TRUE., &123GotForceBC, Found, ComputeMeshVelocity, FirstTime = .TRUE.124125REAL(KIND=dp),ALLOCATABLE:: STIFF(:,:),&126LOAD(:,:),FORCE(:), ElasticModulus(:,:,:),PoissonRatio(:), &127Alpha(:,:), Beta(:)128129SAVE STIFF, LOAD, FORCE, MeshVelocity, AllocationsDone, &130ElasticModulus, PoissonRatio, Alpha, Beta, FirstTime, &131Mesh0, Nodes0132133!------------------------------------------------------------------------------134REAL(KIND=dp) :: at,at0135!------------------------------------------------------------------------------136137!------------------------------------------------------------------------------138! Get variables needed for solution139!------------------------------------------------------------------------------140IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN141142NULLIFY( MeshVelocity )143IF ( TransientSimulation ) THEN144MeshSol => VariableGet( Solver % Mesh % Variables, 'Front Displacement Velocity' )145IF( ASSOCIATED( MeshSol ) ) THEN146MeshVelocity => MeshSol % Values147END IF148END IF149150MeshSol => Solver % Variable151MeshPerm => MeshSol % Perm152STDOFs = MeshSol % DOFs153MeshUpdate => MeshSol % Values154155LocalNodes = COUNT( MeshPerm > 0 )156IF ( LocalNodes <= 0 ) RETURN157158!------------------------------------------------------------------------------159160UNorm = Solver % Variable % Norm161162IF(FirstTime) THEN163FirstTime = .FALSE.164165InitXVar => VariableGet( Solver % Mesh % Variables, "InitX", UnfoundFatal=.TRUE.)166InitYVar => VariableGet( Solver % Mesh % Variables, "InitY", UnfoundFatal=.TRUE.)167168NoNodes = Solver % Mesh % NumberOfNodes169ALLOCATE( Nodes0 )170ALLOCATE( Nodes0 % x(NoNodes), Nodes0 % y(NoNodes),Nodes0 % z(NoNodes))171DO i=1,NoNodes172Nodes0 % x(i) = Solver % Mesh % Nodes % x(i)173Nodes0 % y(i) = Solver % Mesh % Nodes % y(i)174175!Save initial coordinates to variables too, for dirichlet condition176InitXVar % Values(InitXVar % Perm(i)) = Solver % Mesh % Nodes % x(i)177InitYVar % Values(InitYVar % Perm(i)) = Solver % Mesh % Nodes % y(i)178END DO179180Mesh0 => AllocateMesh()181Mesh0 = Solver % Mesh182Mesh0 % Nodes => Nodes0183Mesh0 % Name = TRIM(Solver % Mesh % Name)//'_reference'184185CALL INFO('FrontDisplacement','Saved the initial mesh for remeshing')186END IF187Solver % Mesh => Mesh0188189190!------------------------------------------------------------------------------191! Allocate some permanent storage, this is done first time only192!------------------------------------------------------------------------------193IF ( .NOT. AllocationsDone .OR. Solver % Mesh % Changed ) THEN194N = Solver % Mesh % MaxElementDOFs195196IF ( AllocationsDone ) THEN197DEALLOCATE( ElasticModulus, PoissonRatio, &198FORCE, Alpha, Beta, STIFF, LOAD, STAT=istat )199END IF200201ALLOCATE( &202Alpha(3,N), Beta(N), &203ElasticModulus( 6,6,N ), PoissonRatio( N ), &204FORCE( STDOFs*N ), STIFF( STDOFs*N,STDOFs*N ), &205LOAD( 4,N ),STAT=istat )206207IF ( istat /= 0 ) THEN208CALL Fatal( 'MeshSolve', 'Memory allocation error.' )209END IF210211!------------------------------------------------------------------------------212AllocationsDone = .TRUE.213!------------------------------------------------------------------------------214END IF215!------------------------------------------------------------------------------216!------------------------------------------------------------------------------217! Do some additional initialization, and go for it218!------------------------------------------------------------------------------219at = CPUTime()220at0 = RealTime()221222CALL Info( 'MeshSolve', ' ', Level=4 )223CALL Info( 'MeshSolve', '-------------------------------------', Level=4 )224CALL Info( 'MeshSolve', 'MESH UPDATE SOLVER:', Level=4 )225CALL Info( 'MeshSolve', '-------------------------------------', Level=4 )226CALL Info( 'MeshSolve', ' ', Level=4 )227CALL Info( 'MeshSolve', 'Starting assembly...', Level=4 )228!------------------------------------------------------------------------------229CALL DefaultInitialize()230!------------------------------------------------------------------------------231DO t=1,Solver % NumberOfActiveElements232233IF ( RealTime() - at0 > 1.0 ) THEN234WRITE(Message,'(a,i3,a)' ) ' Assembly: ', INT(100.0 - 100.0 * &235(Solver % NumberOfActiveElements-t) / &236(1.0*Solver % NumberOfActiveElements)), ' % done'237238CALL Info( 'MeshSolve', Message, Level=5 )239240at0 = RealTime()241END IF242243Element => GetActiveElement(t)244nd = GetElementNOFDOFs()245nb = GetElementNOFBDOFs()246n = GetElementNOFNodes()247248Material => GetMaterial()249250ElasticModulus(1,1,1:n) = GetReal( Material, &251'Mesh Elastic Modulus', Found )252IF ( .NOT. Found ) THEN253ElasticModulus(1,1,1:n) = GetReal( Material, &254'Youngs Modulus', Found )255END IF256IF ( .NOT. Found ) ElasticModulus(1,1,1:n) = 1.0d0257258PoissonRatio(1:n) = GetReal( Material, &259'Mesh Poisson Ratio', Found )260IF ( .NOT. Found ) THEN261PoissonRatio(1:n) = GetReal( Material, &262'Poisson Ratio', Found )263END IF264IF ( .NOT. Found ) PoissonRatio(1:n) = 0.25d0265266!------------------------------------------------------------------------------267! Get element local stiffness & mass matrices268!------------------------------------------------------------------------------269CALL LocalMatrix( STIFF, FORCE, ElasticModulus, &270PoissonRatio, .FALSE., Isotropic, Element, n, nd, nb )271272!------------------------------------------------------------------------------273! Update global matrices from local matrices274!------------------------------------------------------------------------------275CALL DefaultUpdateEquations( STIFF, FORCE )276END DO277278279!------------------------------------------------------------------------------280! Neumann & Newton boundary conditions281!------------------------------------------------------------------------------282DO t = 1, Solver % Mesh % NumberOfBoundaryElements283284Element => GetBoundaryElement(t)285IF ( .NOT.ActiveBoundaryElement() ) CYCLE286IF ( GetElementFamily() == 1 ) CYCLE287288BC => GetBC()289IF ( .NOT. ASSOCIATED(BC) ) CYCLE290291!------------------------------------------------------------------------------292! Force in given direction BC: \tau\cdot n = F293!------------------------------------------------------------------------------294nd = GetElementNOFDOFs()295n = GetElementNOFNodes()296nb = GetElementNOFBDOFs()297298LOAD = 0.0D0299Alpha = 0.0D0300Beta = 0.0D0301302GotForceBC = .FALSE.303LOAD(1,1:n) = GetReal( BC, 'Mesh Force 1', Found )304GotForceBC = GotForceBC.OR.Found305LOAD(2,1:n) = GetReal( BC, 'Mesh Force 2', Found )306GotForceBC = GotForceBC.OR.Found307LOAD(3,1:n) = GetReal( BC, 'Mesh Force 3', Found )308GotForceBC = GotForceBC.OR.Found309310Beta(1:n) = GetReal( BC, 'Mesh Normal Force',Found )311GotForceBC = GotForceBC.OR.Found312313IF ( .NOT.GotForceBC ) CYCLE314315CALL MeshBoundary( STIFF,FORCE, LOAD,Alpha,Beta,Element,n,nd,nb )316317!------------------------------------------------------------------------------318319CALL DefaultUpdateEquations( STIFF, FORCE )320END DO321!------------------------------------------------------------------------------322323CALL DefaultFinishAssembly()324CALL Info( 'MeshSolve', 'Assembly done', Level=4 )325326!------------------------------------------------------------------------------327! Dirichlet boundary conditions328!------------------------------------------------------------------------------329CALL DefaultDirichletBCs()330331!------------------------------------------------------------------------------332CALL Info( 'MeshSolve', 'Set boundaries done', Level=4 )333!------------------------------------------------------------------------------334! Solve the system and check for convergence335!------------------------------------------------------------------------------336PrevUNorm = UNorm337338UNorm = DefaultSolve()339340IF ( UNorm + PrevUNorm /= 0.0d0 ) THEN341RelativeChange = 2*ABS( PrevUNorm - UNorm ) / (PrevUNorm + UNorm)342ELSE343RelativeChange = 0.0d0344END IF345346WRITE( Message, * ) 'Result Norm : ',UNorm347CALL Info( 'MeshSolve', Message, Level=4 )348WRITE( Message, * ) 'Relative Change : ',RelativeChange349CALL Info( 'MeshSolve', Message, Level=4 )350351352IF ( TransientSimulation ) THEN353ComputeMeshVelocity = ListGetLogical( Solver % Values, 'Compute Front Displacement Velocity', Found )354IF ( .NOT. Found ) ComputeMeshVelocity = .TRUE.355356IF ( ComputeMeshVelocity ) THEN357k = MIN( SIZE(Solver % Variable % PrevValues,2), Solver % DoneTime )358359j = ListGetInteger( Solver % Values,'Compute Front Displacement Velocity Order', Found)360IF( Found ) THEN361k = MIN( k, j )362ELSE363k = 1364END IF365366SELECT CASE(k)367CASE(0)368MeshVelocity = 0._dp369CASE(1)370MeshVelocity = ( MeshUpdate - Solver % Variable % PrevValues(:,1) ) / dt371CASE(2)372MeshVelocity = ( &373MeshUpdate - (4.0d0/3.0d0)*Solver % Variable % PrevValues(:,1) &374+ (1.0d0/3.0d0)*Solver % Variable % PrevValues(:,2) ) / dt375CASE DEFAULT376MeshVelocity = ( &377MeshUpdate - (18.0d0/11.0d0)*Solver % Variable % PrevValues(:,1) &378+ ( 9.0d0/11.0d0)*Solver % Variable % PrevValues(:,2) &379- ( 2.0d0/11.0d0)*Solver % Variable % PrevValues(:,3) ) / dt380END SELECT381382ELSE IF( ASSOCIATED( MeshVelocity ) ) THEN383MeshVelocity = 0.0d0384END IF385END IF386387Solver % Mesh => Model % Mesh388NoNodes = Solver % Mesh % NumberOfNodes389390DO i=1,NoNodes391k = MeshPerm(i)392IF(k>0) THEN393k = 2 * (k-1)394MeshUpdate(k+1) = Mesh0 % Nodes % x(i) - Solver % Mesh % Nodes % x(i) + MeshUpdate(k+1)395MeshUpdate(k+1) = MIN(MeshUpdate(k+1),0.0_dp) !Ensure <= 0 (epsilon issues)396397MeshUpdate(k+2) = Mesh0 % Nodes % y(i) - Solver % Mesh % Nodes % y(i) + MeshUpdate(k+2)398ELSE399CALL FATAL('Front Displacement','This is almost certainly a permutation error')400END IF401END DO402403404CONTAINS405406!------------------------------------------------------------------------------407SUBROUTINE LocalMatrix( STIFF,FORCE,NodalYoung, NodalPoisson, &408PlaneStress, Isotropic, Element,n, nd, nb )409!------------------------------------------------------------------------------410IMPLICIT NONE411412REAL(KIND=dp) :: NodalPoisson(:), NodalYoung(:,:,:)413REAL(KIND=dp), TARGET :: STIFF(:,:), FORCE(:)414415INTEGER :: n,nd,nb416417TYPE(Element_t) :: Element418LOGICAL :: PlaneStress, Isotropic419!------------------------------------------------------------------------------420!421REAL(KIND=dp) :: Basis(nd)422REAL(KIND=dp) :: dBasisdx(nd,3),detJ423424REAL(KIND=dp) :: NodalLame1(n),NodalLame2(n),Lame1,Lame2, &425Poisson, Young426427REAL(KIND=dp), POINTER :: A(:,:)428REAL(KIND=dp) :: s,u,v,w429INTEGER :: i,j,k,p,q,t,dim430431LOGICAL :: stat432TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff433434TYPE(Nodes_t) :: Nodes435SAVE Nodes436!------------------------------------------------------------------------------437438CALL GetElementNodes( Nodes )439dim = CoordinateSystemDimension()440441IF ( PlaneStress ) THEN442NodalLame1(1:n) = NodalYoung(1,1,1:n) * NodalPoisson(1:n) / &443((1.0d0 - NodalPoisson(1:n)**2))444ELSE445NodalLame1(1:n) = NodalYoung(1,1,1:n) * NodalPoisson(1:n) / &446((1.0d0 + NodalPoisson(1:n)) * (1.0d0 - 2.0d0*NodalPoisson(1:n)))447END IF448449NodalLame2(1:n) = NodalYoung(1,1,1:n) / (2* (1.0d0 + NodalPoisson(1:n)))450451STIFF = 0.0d0452FORCE = 0.0d0453454! Integration stuff:455! ------------------456IntegStuff = GaussPoints( Element )457458! Now we start integrating:459! -------------------------460DO t=1,IntegStuff % n461u = IntegStuff % u(t)462v = IntegStuff % v(t)463w = IntegStuff % w(t)464465! Basis function values & derivatives at the integration point:466!--------------------------------------------------------------467stat = ElementInfo( Element,Nodes, u, v, w, detJ, &468Basis, dBasisdx )469470s = detJ * IntegStuff % s(t)471472! Lame parameters at the integration point:473! -----------------------------------------474Lame1 = SUM( NodalLame1(1:n)*Basis(1:n) )475Lame2 = SUM( NodalLame2(1:n)*Basis(1:n) )476477478! Loop over basis functions (of both unknowns and weights):479! ---------------------------------------------------------480DO p=1,nd481DO q=p,nd482A => STIFF( dim*(p-1)+1:dim*p,dim*(q-1)+1:dim*q )483DO i=1,dim484DO j = 1,dim485A(i,j) = A(i,j) + s * Lame1 * dBasisdx(q,j) * dBasisdx(p,i)486A(i,i) = A(i,i) + s * Lame2 * dBasisdx(q,j) * dBasisdx(p,j)487A(i,j) = A(i,j) + s * Lame2 * dBasisdx(q,i) * dBasisdx(p,j)488END DO489END DO490END DO491END DO492END DO493494! Assign the symmetric block:495! ---------------------------496DO p=1,dim*nd497DO q=1,p-1498STIFF(p,q)=STIFF(q,p)499END DO500END DO501502IF ( nb == 0 ) THEN503DO p=MAX(n+1,nd-Element % BDOFs+1),nd504DO i=1,dim505j = (p-1)*dim + i506STIFF( j,: ) = 0.0d0507STIFF( :,j ) = 0.0d0508STIFF( j,j ) = 1.0d0509FORCE( j ) = 0.0d0510END DO511END DO512END IF513!------------------------------------------------------------------------------514END SUBROUTINE LocalMatrix515!------------------------------------------------------------------------------516517518!------------------------------------------------------------------------------519SUBROUTINE MeshBoundary( STIFF,FORCE,LOAD,NodalAlpha,NodalBeta,Element,n,nd,nb )520!------------------------------------------------------------------------------521REAL(KIND=dp) :: STIFF(:,:),FORCE(:)522REAL(KIND=dp) :: NodalAlpha(:,:),NodalBeta(:),LOAD(:,:)523TYPE(Element_t),POINTER :: Element524INTEGER :: n,nd,nb525!------------------------------------------------------------------------------526REAL(KIND=dp) :: Basis(nd)527REAL(KIND=dp) :: dBasisdx(nd,3),detJ528529REAL(KIND=dp) :: u,v,w,s530REAL(KIND=dp) :: Alpha(3),Beta,Normal(3),LoadAtIP(3)531532INTEGER :: i,t,q,p,dim533534LOGICAL :: stat535536TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff537538TYPE(Nodes_t) :: Nodes539SAVE Nodes540!------------------------------------------------------------------------------541542dim = Element % TYPE % DIMENSION + 1543CALL GetElementNodes( Nodes )544545FORCE = 0.0D0546STIFF = 0.0D0547!548! Integration stuff549!550IntegStuff = GaussPoints( Element )551!552! Now we start integrating553!554DO t=1,IntegStuff % n555556u = IntegStuff % u(t)557v = IntegStuff % v(t)558w = IntegStuff % w(t)559560!------------------------------------------------------------------------------561! Basis function values & derivatives at the integration point562!------------------------------------------------------------------------------563stat = ElementInfo( Element, Nodes, u, v, w, detJ, &564Basis, dBasisdx )565566s = detJ * IntegStuff % s(t)567!------------------------------------------------------------------------------568LoadAtIP = 0.0D0569DO i=1,dim570LoadAtIP(i) = SUM( LOAD(i,1:n)*Basis )571Alpha(i) = SUM( NodalAlpha(i,1:n)*Basis )572END DO573574Normal = NormalVector( Element,Nodes,u,v,.TRUE. )575LoadAtIP = LoadAtIP + SUM( NodalBeta(1:n)*Basis ) * Normal576577DO p=1,nd578DO q=1,nd579DO i=1,dim580STIFF((p-1)*dim+i,(q-1)*dim+i) = &581STIFF((p-1)*dim+i,(q-1)*dim+i) + &582s * Alpha(i) * Basis(q) * Basis(p)583END DO584END DO585END DO586587DO q=1,nd588DO i=1,dim589FORCE((q-1)*dim+i) = FORCE((q-1)*dim+i) + &590s * Basis(q) * LoadAtIP(i)591END DO592END DO593594END DO595596IF ( nb == 0 ) THEN597DO p=MAX(n+1,nd-Element % BDOFs+1),nd598DO i=1,dim599j = (p-1)*dim + i600STIFF( j,: ) = 0.0d0601STIFF( :,j ) = 0.0d0602STIFF( j,j ) = 1.0d0603FORCE( j ) = 0.0d0604END DO605END DO606END IF607608!------------------------------------------------------------------------------609END SUBROUTINE MeshBoundary610!------------------------------------------------------------------------------611612!------------------------------------------------------------------------------613END SUBROUTINE FDMeshSolver614!------------------------------------------------------------------------------615616617