Path: blob/devel/elmerice/Solvers/AdjointStokes/AdjointStokes_GradientMu.F90
3206 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:25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! *30! *****************************************************************************31! Compute the nodal gradient of the Cost function with respect to the ice32! viscosity for the control inverse method33! (cf Morlighem, M., Ice sheet properties inferred by combining numerical34! modeling and remote sensing data)35!36! Serial/Parallel and 2D/3D37!38! .sif parameters:39! In the Solver section:40! - Flow Solution Name = String ; name of the variable for the direct problem ("Flow Solution" default)41! - Adjoint Solution Name = String ; name of the variable for the Adjoint system ("Adjoint" default)42! - Optimized Variable Name = String ; ("Mu" default)43! - Gradient Variable Name = String ; t ("DJDMu" default)44!45! Sometimes a modified function of viscosity is used such that viscosity != optvar and instead46! viscosity = f(optvar) where optvar is the variable to be optimised. In this case the 'Viscosity47! derivative' must be set in the material section. The USF_CoV functions can be used for this.48! For example, for the case viscosity = optvar^2, viscosity can be set like this in the material section:49! viscosity = variable optvar50! REAL procedure "ElmerIceUSF" "Asquare"51! And the partial derivative can be set like this:52! Viscosity derivative = Variable optvar53! REAL procedure "ElmerIceUSF" "Asquare_d"54!55! Execute this solver in the main ice body in conjunction with :56! -CostSolver_Adjoint.f90: To compute the cost function;57! !!ATTENTION!! : No regularistaion yet put Lamda=Real 0.0 for the computation of the cost function58! -Optimise_m1qn3[Serial/Parallel].f90: for the optimization59!60! *****************************************************************************61SUBROUTINE AdjointStokes_GradientMuSolver( Model,Solver,dt,TransientSimulation )62!------------------------------------------------------------------------------63!******************************************************************************64USE DefUtils65USE MaterialModels66IMPLICIT NONE67!------------------------------------------------------------------------------68TYPE(Solver_t) :: Solver69TYPE(Model_t) :: Model7071REAL(KIND=dp) :: dt72LOGICAL :: TransientSimulation73!74!!!! Variables utiles pour les elements et les fonctions de base75TYPE(Element_t),POINTER :: Element76TYPE(Nodes_t) :: ElementNodes77TYPE(GaussIntegrationPoints_t) :: IntegStuff78TYPE(ValueList_t), POINTER :: SolverParams,Material79TYPE(ValueList_t), POINTER :: BC8081real(kind=dp),allocatable :: Basis(:),dBasisdx(:,:)82real(kind=dp) :: u,v,w,SqrtElementMetric83INTEGER, POINTER :: NodeIndexes(:)84CHARACTER(LEN=MAX_NAME_LEN) :: SolverName8586!!!!! variables Elmer87TYPE(Variable_t), POINTER :: GradVariable, Variable, VeloSolN,VeloSolD88REAL(KIND=dp), POINTER :: GradValues(:),VelocityN(:),VelocityD(:)89INTEGER, POINTER :: GradPerm(:), VeloNPerm(:),VeloDPerm(:)90CHARACTER(LEN=MAX_NAME_LEN) ::GradSolName,NeumannSolName,DirichletSolName9192!! autres variables93real(kind=dp),allocatable :: VisitedNode(:),db(:)94real(kind=dp),allocatable,dimension(:) :: Ux,Uy,Uz95real(kind=dp) :: Velo(3),dVelodx(3,3)96real(kind=dp) :: s,ss,c2,c397real(kind=dp) :: mub,Viscosityb98real(kind=dp),allocatable,dimension(:) :: c2n,c3n99real(kind=dp),allocatable,dimension(:) :: NodalViscosityb100REAL(kind=dp),allocatable,SAVE :: NodalDer(:)101LOGICAL :: HaveDer102103integer :: i,j,t,n,NMAX,NpN,DIM,e,p,q104105CHARACTER(LEN=MAX_NAME_LEN) :: ViscosityFlag106107Logical :: Firsttime=.true.,Found,stat,gotit,UnFoundFatal=.TRUE.108109110save Firsttime,DIM111save ElementNodes112save SolverName113save NeumannSolName,DirichletSolName,GradSolName114save VisitedNode,db,Basis,dBasisdx115save Ux,Uy,Uz116save c2n,c3n117save NodalViscosityb118119!!!! Firsttime Do some allocation and initialisation120If (Firsttime) then121122DIM = CoordinateSystemDimension()123WRITE(SolverName, '(A)') 'DJDMu_Adjoint'124125NMAX=Solver % Mesh % NumberOfNodes126NpN=Model % MaxElementNodes127128allocate(VisitedNode(NMAX),db(NMAX), &129Basis(NpN), &130dBasisdx(NpN,3), &131Ux(NpN),Uy(NpN),Uz(NpN),&132c2n(NpN),c3n(NpN),&133NodalViscosityb(NpN))134135allocate(NodalDer(NMAX))136137!!!!!!!!!!! get Solver Variables138SolverParams => GetSolverParams()139140NeumannSolName = GetString( SolverParams,'Flow Solution Name', Found)141IF(.NOT.Found) THEN142CALL WARN(SolverName,'Keyword >Flow Solution Name< not found in section >Solver<')143CALL WARN(SolverName,'Taking default value >Flow Solution<')144WRITE(NeumannSolName,'(A)') 'Flow Solution'145END IF146DirichletSolName = GetString( SolverParams,'Adjoint Solution Name', Found)147IF(.NOT.Found) THEN148CALL WARN(SolverName,'Keyword >Adjoint Solution Name< not found in section >Solver<')149CALL WARN(SolverName,'Taking default value >VeloD<')150WRITE(DirichletSolName,'(A)') 'VeloD'151END IF152GradSolName = GetString( SolverParams,'Gradient Variable Name', Found)153IF(.NOT.Found) THEN154CALL WARN(SolverName,'Keyword >Gradient Variable Name< not found in section >Solver<')155CALL WARN(SolverName,'Taking default value >DJDMu<')156WRITE(GradSolName,'(A)') 'DJDmu'157END IF158159!!! End of First visit160Firsttime=.false.161Endif162163! Get variables needed by the Solver164165GradVariable => VariableGet( Solver % Mesh % Variables, GradSolName,UnFoundFatal=UnFoundFatal)166GradValues => GradVariable % Values167GradPerm => GradVariable % Perm168GradValues=0._dp169170VeloSolN => VariableGet( Solver % Mesh % Variables, NeumannSolName,UnFoundFatal=UnFoundFatal)171VelocityN => VeloSolN % Values172VeloNPerm => VeloSolN % Perm173174VeloSolD => VariableGet( Solver % Mesh % Variables, DirichletSolName,UnFoundFatal=UnFoundFatal)175VelocityD => VeloSolD % Values176VeloDPerm => VeloSolD % Perm177178VisitedNode=0.0_dp179db=0.0_dp180181Elements: DO e=1,Solver % NumberOfActiveElements182183Element => GetActiveElement(e)184Material => GetMaterial()185CALL GetElementNodes( ElementNodes )186n = GetElementNOFNodes()187NodeIndexes => Element % NodeIndexes188189NodalDer(1:n) = ListGetReal(Material,'Viscosity derivative',n,NodeIndexes,Found=HaveDer)190191VisitedNode(NodeIndexes(1:n))=VisitedNode(NodeIndexes(1:n))+1.0_dp192193Ux=0.0_dp194Uy=0.0_dp195Uz=0.0_dp196Ux(1:n)=VelocityN((DIM+1)*(VeloNPerm(NodeIndexes(1:n))-1)+1)197Uy(1:n)=VelocityN((DIM+1)*(VeloNPerm(NodeIndexes(1:n))-1)+2)198If (DIM.eq.3) Uz(1:n)=VelocityN((DIM+1)*(VeloNPerm(NodeIndexes(1:n))-1)+3)199200!!!!201nodalViscosityb=0.0_dp202203IntegStuff = GaussPoints( Element )204205IPs: DO t=1,IntegStuff%n206207u = IntegStuff % u(t)208v = IntegStuff % v(t)209w =IntegStuff % w(t)210211stat = ElementInfo( Element, ElementNodes, u, v, w,SqrtElementMetric, &212Basis, dBasisdx) !removed bubbles213214s = SqrtElementMetric * IntegStuff % s(t)215216mub=0.0_dp217p_loop: DO p=1,n218q_loop: DO q=1,n219i_loop: DO i=1,DIM220j_loop: DO j=1,DIM221mub=mub+ s * dBasisdx(q,j) * dBasisdx(p,j) * &222(- VelocityN((DIM+1)*(VeloNPerm(NodeIndexes(q))-1)+i) * &223VelocityD((DIM+1)*(VeloDPerm(NodeIndexes(p))-1)+i))224225mub=mub+ s * dBasisdx(q,i) * dBasisdx(p,j) * &226(- VelocityN((DIM+1)*(VeloNPerm(NodeIndexes(q))-1)+j) * &227& VelocityD((DIM+1)*(VeloDPerm(NodeIndexes(p))-1)+i))228END DO j_loop229END DO i_loop230END DO q_loop231END DO p_loop232233ViscosityFlag = ListGetString( Material,'Viscosity Model', GotIt,UnFoundFatal)234235SELECT CASE( ViscosityFlag )236CASE('power law')237DO j=1,3238dVelodx(1,j) = SUM( Ux(1:n)*dBasisdx(1:n,j) )239dVelodx(2,j) = SUM( Uy(1:n)*dBasisdx(1:n,j) )240dVelodx(3,j) = SUM( Uz(1:n)*dBasisdx(1:n,j) )241END DO242243Velo(1) = SUM( Basis(1:n) * Ux(1:n) )244Velo(2) = SUM( Basis(1:n) * Uy(1:n) )245Velo(3) = SUM( Basis(1:n) * Uz(1:n) )246247ss = SecondInvariant(Velo,dVelodx)/2248249c2n = ListGetReal( Material, 'Viscosity Exponent', n, NodeIndexes )250c2 = SUM( Basis(1:n) * c2n(1:n) )251252s = ss253254c3n = ListGetReal( Material, 'Critical Shear Rate',n, NodeIndexes ,gotIt )255IF (GotIt) THEN256c3 = SUM( Basis(1:n) * c3n(1:n) )257IF(s < c3**2) THEN258s = c3**2259END IF260END IF261262Viscosityb=mub*s**((c2-1)/2)263264CASE default265CALL FATAL(SolverName,'Viscosity Model has to be power Law')266END SELECT267268nodalViscosityb(1:n)=nodalViscosityb(1:n)+Viscosityb*Basis(1:n)269END DO IPs270271IF (HaveDer) THEN272nodalViscosityb(1:n)=nodalViscosityb(1:n)*NodalDer(1:n)273END IF274275db(NodeIndexes(1:n)) = db(NodeIndexes(1:n)) + nodalViscosityb(1:n)276END DO Elements277278DO t=1,Solver % Mesh % NumberOfNodes279IF (VisitedNode(t).LT.1.0_dp) CYCLE280GradValues(GradPerm(t))=db(t)281END DO282283RETURN284285!------------------------------------------------------------------------------286END SUBROUTINE AdjointStokes_GradientMuSolver287!------------------------------------------------------------------------------288289290291292