!/*****************************************************************************/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, Ga¨el Durand, Mondher Chekki25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! * Modify on 15/12/2018: Add support to Parallel Solver3031! ****************************************************************************/32! -----------------------------------------------------------------------33!> Solver to go from a Force (or Debit) to Stress (or Flux) SDOFs = 134RECURSIVE SUBROUTINE ForceToStress( Model,Solver,dt,TransientSimulation )35!------------------------------------------------------------------------------3637USE DefUtils38USE ElmerIceUtils3940IMPLICIT NONE4142!------------------------------------------------------------------------------43!******************************************************************************44!45! Solve stress equations for one timestep46!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! REAL(KIND=dp) :: dt,56! INPUT: Timestep size for time dependent simulations (NOTE: Not used57! currently)58!59!******************************************************************************6061TYPE(Model_t) :: Model62TYPE(Solver_t), TARGET :: Solver6364LOGICAL :: TransientSimulation65REAL(KIND=dp) :: dt66!------------------------------------------------------------------------------67! Local variables68!------------------------------------------------------------------------------69TYPE(Solver_t), POINTER :: PSolver7071TYPE(Matrix_t), POINTER :: StiffMatrix7273INTEGER :: i, j, k, l, n, t, iter, NDeg, STDOFs, LocalNodes, istat74INTEGER :: dim7576TYPE(ValueList_t),POINTER :: Material, BC77TYPE(Nodes_t) :: ElementNodes78TYPE(Element_t),POINTER :: CurrentElement79TYPE(Element_t),POINTER :: Element8081REAL(KIND=dp) :: RelativeChange, UNorm, PrevUNorm, s8283LOGICAL :: stat, CSymmetry, IsPeriodicBC, Found8485INTEGER :: NewtonIter, NonlinearIter, bc_Id8687TYPE(Variable_t), POINTER :: StressSol, ForceSol8889REAL(KIND=dp), POINTER :: Stress(:), ForceValues(:), &90ForceVector(:)9192INTEGER, POINTER :: StressPerm(:), ForcePerm(:), NodeIndexes(:)9394LOGICAL :: GotIt, AllocationsDone = .FALSE.,UnFoundFatal=.TRUE.9596REAL(KIND=dp), ALLOCATABLE:: LocalMassMatrix(:,:), &97LocalStiffMatrix(:,:), LocalForce(:), &98NodalForce(:)99100CHARACTER(LEN=MAX_NAME_LEN) :: SolverName, InputVariableName101REAL(KIND=dp) :: at, at0102INTEGER :: nlen103CHARACTER(LEN=MAX_NAME_LEN) :: VarName104REAL(KIND=dp) , ALLOCATABLE :: ForceValues_tmp(:)105106!------------------------------------------------------------------------------107SAVE LocalMassMatrix, LocalStiffMatrix, LocalForce, &108ElementNodes, AllocationsDone109SAVE NodalForce, dim110111!------------------------------------------------------------------------------112! Get Force variable113!------------------------------------------------------------------------------114SolverName = 'ForceToStress'115116InputVariableName = GetString( Solver % Values, 'Force Variable Name', GotIt )117IF (.NOT.GotIt) THEN118InputVariableName = 'Force'119CALL INFO(SolverName,'Force Variable Name sets to Force',Level=4)120END IF121122ForceSol => VariableGet( Solver % Mesh % Variables, InputVariableName,UnFoundFatal=UnFoundFatal)123ForcePerm => ForceSol % Perm124ForceValues => ForceSol % Values125126!------------------------------------------------------------------------------127! Allocate temporary storage128!------------------------------------------------------------------------------129ALLOCATE( ForceValues_tmp(SIZE(ForceValues)), STAT=istat )130IF ( istat /= 0 ) THEN131CALL Fatal( SolverName, 'Memory allocation error.' )132END IF133!------------------------------------------------------------------------------134! Get variables needed for solution135!------------------------------------------------------------------------------136IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN137138StressSol => Solver % Variable139StressPerm => StressSol % Perm140STDOFs = StressSol % DOFs141Stress => StressSol % Values142143LocalNodes = COUNT( StressPerm > 0 )144IF ( LocalNodes <= 0 ) RETURN145146147StiffMatrix => Solver % Matrix148ForceVector => StiffMatrix % RHS149UNorm = Solver % Variable % Norm150151!------------------------------------------------------------------------------152! Allocate some permanent storage, this is done first time only153!------------------------------------------------------------------------------154IF ( .NOT. AllocationsDone .OR. Solver % MeshChanged) THEN155N = Model % MaxElementNodes156dim = CoordinateSystemDimension()157158IF ( AllocationsDone ) THEN159DEALLOCATE( ElementNodes % x, &160ElementNodes % y, &161ElementNodes % z, &162NodalForce, &163LocalMassMatrix, &164LocalStiffMatrix, &165LocalForce )166END IF167168ALLOCATE( ElementNodes % x( N ), &169ElementNodes % y( N ), &170ElementNodes % z( N ), &171NodalForce(N ), &172LocalMassMatrix( 2*STDOFs*N,2*STDOFs*N ), &173LocalStiffMatrix( 2*STDOFs*N,2*STDOFs*N ), &174LocalForce( 2*STDOFs*N ), STAT=istat )175176IF ( istat /= 0 ) THEN177CALL Fatal( SolverName, 'Memory allocation error.' )178END IF179!------------------------------------------------------------------------------180AllocationsDone = .TRUE.181END IF182183!------------------------------------------------------------------------------184! Update Force solution on Parallel Partitions185!------------------------------------------------------------------------------186VarName=GetVarName(Solver % Variable)187188CALL UpdatePartitionWeight(Model, Solver, VarName, ForceSol, ForceValues_tmp)189!------------------------------------------------------------------------------190NonlinearIter = 1191DO iter=1,NonlinearIter192193at = CPUTime()194at0 = RealTime()195196CALL Info( SolverName, 'Starting assembly...',Level=4 )197198!------------------------------------------------------------------------------199CALL DefaultInitialize()200!------------------------------------------------------------------------------201DO t=1,Solver % NumberOFActiveElements202203IF ( RealTime() - at0 > 1.0 ) THEN204WRITE(Message,'(a,i3,a)' ) ' Assembly: ', &205INT(100.0 - 100.0 * (Solver % NumberOfActiveElements-t) / &206(1.0*Solver % NumberOfActiveElements)), ' % done'207CALL Info( SolverName, Message, Level=5 )208at0 = RealTime()209END IF210211CurrentElement => GetActiveElement(t)212n = GetElementNOFNodes()213NodeIndexes => CurrentElement % NodeIndexes214215ElementNodes % x(1:n) = Model % Nodes % x(NodeIndexes(1:n))216ElementNodes % y(1:n) = Model % Nodes % y(NodeIndexes(1:n))217ElementNodes % z(1:n) = Model % Nodes % z(NodeIndexes(1:n))218219Material => GetMaterial()220221!------------------------------------------------------------------------------222! Get element local stiffness & mass matrices223!------------------------------------------------------------------------------224225CALL LocalMatrix( LocalMassMatrix, LocalStiffMatrix, &226CurrentElement, n, ElementNodes )227228!------------------------------------------------------------------------------229! Update global matrices from local matrices230!------------------------------------------------------------------------------231CALL DefaultUpdateEquations( LocalStiffMatrix, LocalForce )232233END DO234235DO i=1, Model % Mesh % NumberOfNodes236IF (StressPerm(i)>0) THEN237ForceVector(StressPerm(i)) = ForceValues_tmp(ForcePerm(i))238END IF239END DO240241!------------------------------------------------------------------------------242! Deallocate temporary storage243!------------------------------------------------------------------------------244DEALLOCATE(ForceValues_tmp)245!------------------------------------------------------------------------------246! Special traitment for nodes belonging in periodic boundary (F = 0)247!------------------------------------------------------------------------------248CALL SetZeroAtPeriodicNodes(Model, Solver, VarName, ForceVector, ForcePerm, StressPerm)249250CALL Info( SolverName, 'Assembly done', Level=4 )251252CALL DefaultFinishAssembly()253254!------------------------------------------------------------------------------255! Dirichlet boundary conditions256!------------------------------------------------------------------------------257! Only needed to account for periodic BC258!259CALL DefaultDirichletBCs()260261!------------------------------------------------------------------------------262263CALL Info( SolverName, 'Set boundaries done', Level=4 )264265!------------------------------------------------------------------------------266! Solve the system and check for convergence267!------------------------------------------------------------------------------268PrevUNorm = UNorm269270UNorm = DefaultSolve()271272unorm = 0273n = Solver % Variable % DOFs274DO i=1,n-1275unorm = unorm + SUM( solver % variable % values(i::n)**2 )276END DO277278unorm = SQRT( unorm )279280solver % variable % norm = unorm281282IF ( PrevUNorm + UNorm /= 0.0d0 ) THEN283RelativeChange = 2.0d0 * ABS( PrevUNorm - UNorm) / ( PrevUnorm + UNorm)284ELSE285RelativeChange = 0.0d0286END IF287288WRITE( Message, * ) 'Result Norm : ',UNorm, PrevUNorm289CALL Info( SolverName, Message, Level=4 )290WRITE( Message, * ) 'Relative Change : ',RelativeChange291CALL Info( SolverName, Message, Level=4 )292293294!------------------------------------------------------------------------------295END DO ! of nonlinear iter296!------------------------------------------------------------------------------297298299CONTAINS300301302!------------------------------------------------------------------------------303SUBROUTINE LocalMatrix( MassMatrix, StiffMatrix, &304Element, n, Nodes )305306!------------------------------------------------------------------------------307308REAL(KIND=dp) :: StiffMatrix(:,:), MassMatrix(:,:)309TYPE(Nodes_t) :: Nodes310TYPE(Element_t) :: Element311INTEGER :: n312!------------------------------------------------------------------------------313!314REAL(KIND=dp) :: Basis(2*n), ddBasisddx(1,1,1)315REAL(KIND=dp) :: dBasisdx(2*n,3), detJ316317REAL(KIND=dp) :: LGrad(3,3), SR(3,3), Li(9)318319INTEGER :: i, j, k, p, q, t, dim, cc320321REAL(KIND=dp) :: s, u, v, w, Radius322323TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff324325INTEGER :: N_Integ326327REAL(KIND=dp), DIMENSION(:), POINTER :: U_Integ, V_Integ, W_Integ, S_Integ328329LOGICAL :: stat, CSymmetry330331!------------------------------------------------------------------------------332333StiffMatrix = 0.0D0334MassMatrix = 0.0D0335336IntegStuff = GaussPoints( Element )337338U_Integ => IntegStuff % u339V_Integ => IntegStuff % v340W_Integ => IntegStuff % w341S_Integ => IntegStuff % s342N_Integ = IntegStuff % n343!344! Now we start integrating345!346DO t=1,N_Integ347348u = U_Integ(t)349v = V_Integ(t)350w = W_Integ(t)351352!------------------------------------------------------------------------------353! Basis function values & derivatives at the integration point354!------------------------------------------------------------------------------355stat = ElementInfo(Element,Nodes,u,v,w,detJ, &356Basis,dBasisdx,ddBasisddx,.FALSE.,.FALSE.)357358359s = detJ * S_Integ(t)360361362Radius = SUM( Nodes % x(1:n) * Basis(1:n) )363CSymmetry = CurrentCoordinateSystem() == AxisSymmetric364IF ( CSymmetry ) s = s * Radius365366367DO p=1,n368DO q=1,n369StiffMatrix(p,q) = &370StiffMatrix(p,q) + s*Basis(q)*Basis(p)371END DO372END DO373END DO374375!------------------------------------------------------------------------------376END SUBROUTINE LocalMatrix377!------------------------------------------------------------------------------378379!------------------------------------------------------------------------------380END SUBROUTINE ForceToStress381!------------------------------------------------------------------------------382383384