Path: blob/devel/elmerice/UserFunctions/USF_ShapeFactor.F90
3196 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 Gagliardini25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! *30! *****************************************************************************31!> Shape Factor user functions32!>33!> return the gravity force -g + (1-f)(g.t).t34!> where t is the tangent vector of the surface35!> end f is the shape factor36!> work only in 2D (no sense in 3D)37!> work for non-structured mesh38!> f can be given or calculated as a function of H(x,t) (height)39!> for different shape (rectangle, parabola, shelf)40FUNCTION ShapeFactorGravity_x ( Model, nodenumber, x) RESULT(gx)41USE Types42USE DefUtils43IMPLICIT NONE44TYPE(Model_t) :: Model45INTEGER :: nodenumber46REAL(KIND=dp) :: x, gx, ShapeFactorGravity4748gx = ShapeFactorGravity ( Model, nodenumber, x, 1 )495051END FUNCTION ShapeFactorGravity_x5253FUNCTION ShapeFactorGravity_y ( Model, nodenumber, x) RESULT(gy)54USE Types55USE DefUtils56IMPLICIT NONE57TYPE(Model_t) :: Model58INTEGER :: nodenumber59REAL(KIND=dp) :: x, gy, ShapeFactorGravity6061gy = ShapeFactorGravity ( Model, nodenumber, x, 2 )6263END FUNCTION ShapeFactorGravity_y6465666768FUNCTION ShapeFactorGravity ( Model, nodenumber, x, axis ) RESULT(gi)69USE types70USE GeneralUtils71USE CoordinateSystems72USE SolverUtils73USE ElementDescription74USE DefUtils75IMPLICIT NONE76TYPE(Model_t) :: Model77INTEGER :: nodenumber, axis78REAL(KIND=dp) :: x, gi7980TYPE(Nodes_t), SAVE :: Nodes81TYPE(variable_t), POINTER :: Timevar82TYPE(Element_t), POINTER :: BoundaryElement, BCElement, CurElement, ParentElement83TYPE(ValueList_t), POINTER :: BodyForce, BC848586REAL(KIND=dp), ALLOCATABLE :: zs(:), xs(:), ts(:,:), zb(:), xb(:)87REAL(KIND=dp), TARGET, ALLOCATABLE :: z2s(:), z2b(:), ts2x(:), ts2y(:), para2(:)88REAL(KIND=dp), DIMENSION(:), POINTER :: z2s_p, z2b_p, ts2x_p, ts2y_p, para2_p89REAL(KIND=dp), ALLOCATABLE :: auxReal(:), para(:)90REAL(KIND=dp) :: t, t0, told, Bu, Bv, f, afactor, width, H, w, NVelo91REAL(KIND=dp) :: g(2), tangent(2), normal(3), Velo(2)9293INTEGER, ALLOCATABLE :: ind(:), NodesOnSurface(:), NodesOnBed(:)94INTEGER, ALLOCATABLE :: TempS(:), TempB(:)95INTEGER :: Ns, Nb96INTEGER ::i, j, n, k, p, DIM9798LOGICAL :: FirstTime = .TRUE., NewTime, GotIt99LOGICAL :: Parabola, Rectangle, Computed=.TRUE.100LOGICAL :: Bedrock, Surface101102!--------------------------------------------103! Parameter for the shape function definition104! f(w) = 2/ (n pi) sum_i=1^n ATAN(a(i) x w^i)105!--------------------------------------------106INTEGER, PARAMETER :: nr=6, np=1107REAL(KIND=dp), PARAMETER :: ap(np) = (/0.814589_dp/), &108ar(nr) = (/5.30904_dp,0.0934244_dp,3.94177_dp,74.6014_dp,0.0475342_dp,1.35021_dp/)109110SAVE told, t0, FirstTime, NewTime, g111SAVE zs, xs, ts, zb, xb, Ns, Nb, para, auxReal112SAVE z2s, z2b, ts2x, ts2y, para2113SAVE Parabola, Rectangle, Computed114SAVE NodesOnSurface, NodesOnBed, TempS, TempB115116Timevar => VariableGet( Model % Variables,'Time')117t = TimeVar % Values(1)118119IF (FirstTime) THEN120! STOP if we are not solving a 2D flow line problem121DIM = CoordinateSystemDimension()122IF ( DIM /= 2 ) THEN123CALL FATAL('ShapeFactorGravity','Work only for 2D flow line problem')124END IF125126FirstTime = .FALSE.127NewTime = .TRUE.128told = t129t0 = t130131n = Model % MaxElementNodes132ALLOCATE( auxReal(n) )133134BodyForce => GetBodyForce()135136!-------------------------137! Get the gravity vector g138!-------------------------139g(1) = GetConstReal( BodyForce, 'Shape Gravity 1', GotIt )140g(2) = GetConstReal( BodyForce, 'Shape Gravity 2', GotIt )141IF ( .Not.GotIt ) CALL FATAL('ShapeFactorGravity', &142'Gravity vector must be specified')143144!---------------------------------------------145! Determine how is calculated the shape factor146!---------------------------------------------147Parabola = GetLogical( BodyForce, 'Parabola Shape', GotIt)148IF (.Not.GotIt) Parabola = .FALSE.149Rectangle = GetLogical( BodyForce, 'Rectangle Shape', GotIt)150IF (.Not.GotIt) Rectangle = .FALSE.151IF (Rectangle.AND.Parabola) CALL FATAL('ShapeFactorGravity', &152'Make a choice between Parabola or Rectangle shapes')153IF ((.Not.Rectangle).AND.(.Not.Parabola)) THEN154Computed = .FALSE.155CurElement => Model % CurrentElement156n = CurElement % Type % NumberOfNodes157auxReal(1:n) = GetReal( BodyForce, &158'Shape Factor', GotIt )159IF ( .Not.GotIt ) CALL FATAL('ShapeFactorGravity', &160'Shape Factor must be given or Computed')161END IF162163164!-------------------------------------------165! Number of nodes on the bed and the surface166!-------------------------------------------167CurElement => Model % CurrentElement168Ns = 1169Nb = 1170DO p = 1, Model % NumberOfBoundaryElements171BCElement => GetBoundaryElement(p)172BC => GetBC( BCElement )173IF( GetElementFamily(BCElement) == 1 ) CYCLE174Surface = .FALSE.175Bedrock = .FALSE.176Surface = GetLogical( BC, 'Shape Surface', GotIt)177Bedrock = GetLogical( BC, 'Shape Bedrock', GotIt)178IF (Surface) THEN179n = BCElement % Type % NumberOfNodes180Ns = Ns + n - 1181ELSE IF (Bedrock) THEN182n = BCElement % Type % NumberOfNodes183Nb = Nb + n - 1184END IF185END DO186Model % CurrentElement => CurElement187188IF ((Ns==0).OR.(Nb==0)) CALL FATAL('ShapeFactorGravity', &189'Shape Surface and/or Shape Bedrock not defined')190191ALLOCATE ( zs(Ns), ts(2,Ns), xs(Ns), xb(Nb), zb(Nb) )192ALLOCATE (z2s(Ns), z2b(Ns), ts2x(Ns), ts2y(Ns) )193ALLOCATE ( NodesOnSurface(Ns), NodesOnBed(Nb), TempS(Ns), TempB(Nb) )194IF (Computed) ALLOCATE( para(Ns), para2(Ns) )195196197!-----------------------------------------------------198! Store the nodes number on the bed and on the surface199!-----------------------------------------------------200CurElement => Model % CurrentElement201Ns = 0202Nb = 0203NodesOnSurface = 0204NodesOnBed = 0205DO p = 1, Model % NumberOfBoundaryElements206BCElement => GetBoundaryElement(p)207BC => GetBC( BCElement )208IF( GetElementFamily(BCElement) == 1 ) CYCLE209Surface = .FALSE.210Bedrock = .FALSE.211Surface = GetLogical( BC, 'Shape Surface', GotIt)212Bedrock = GetLogical( BC, 'Shape Bedrock', GotIt)213IF (Surface) THEN214n = BCElement % Type % NumberOfNodes215DO i = 1, n216j = BCElement % NodeIndexes(i)217IF (.NOT.ANY(NodesOnSurface == j )) THEN218Ns = Ns + 1219NodesOnSurface(Ns) = j220xs(Ns) = Model % Nodes % x( j )221END IF222END DO223ELSE IF (Bedrock) THEN224n = BCElement % Type % NumberOfNodes225DO i = 1, n226j = BCElement % NodeIndexes(i)227IF (.NOT.ANY(NodesOnBed == j )) THEN228Nb = Nb + 1229NodesOnBed(Nb) = j230xb(Nb) = Model % Nodes % x( j )231END IF232END DO233END IF234END DO235Model % CurrentElement => CurElement236237!------------------------------------------238! Get ordered NodesOnSurface and NodesOnBed239! SortD : sort in increase order240!------------------------------------------241ALLOCATE (ind(Ns))242ind = (/(i,i=1,Ns)/)243CALL SortD(Ns,xs,ind)244NodesOnSurface = NodesOnSurface(ind)245DEALLOCATE(ind)246ALLOCATE (ind(Nb))247ind = (/(i,i=1,Nb)/)248CALL SortD(Nb,xb,ind)249NodesOnBed = NodesOnBed(ind)250DEALLOCATE(ind)251252!----------------------------------------253! If Computed254! Get the width of the rectangle channel255! Get the afactor of the parabola channel256!----------------------------------------257IF (Computed) THEN258CurElement => Model % CurrentElement259DO p = 1, Model % NumberOfBoundaryElements260BCElement => GetBoundaryElement(p)261BC => GetBC( BCElement )262IF( GetElementFamily(BCElement) == 1 ) CYCLE263Surface = .FALSE.264Surface = GetLogical( BC, 'Shape Surface', GotIt)265IF (Surface) THEN266n = BCElement % Type % NumberOfNodes267IF (Parabola) THEN268auxReal(1:n) = GetReal( BodyForce, &269'Parabola aFactor', GotIt )270IF (.Not.GotIt) CALL FATAL('ShapeFactorGravity', &271'Parabola aFactor must be given for Parabola shape')272ELSE IF (Rectangle) THEN273auxReal(1:n) = GetReal( BodyForce, &274'Rectangle Width', GotIt )275IF ((.Not.GotIt).AND.Rectangle) CALL FATAL('ShapeFactorGravity', &276'Rectangle Width must be given for Rectangle shape')277END IF278DO i = 1, n279j = BCElement % NodeIndexes(i)280TempS = 0281WHERE (NodesOnSurface==j) TempS = 1282k = MAXLOC(TempS, dim=1)283para(k) = auxReal(i)284END DO285END IF286END DO287Model % CurrentElement => CurElement288END IF289290ELSE291IF (t > told) THEN292NewTime = .TRUE.293told = t294END IF295ENDIF296297IF (NewTime) THEN298NewTime = .FALSE.299!---------------------------------------------300! Nodal value of zs, zb, tangent for that time301!---------------------------------------------302ts = 0.0_dp303CurElement => Model % CurrentElement304DO p = 1, Model % NumberOfBoundaryElements305BCElement => GetBoundaryElement(p)306BC => GetBC( BCElement )307IF( GetElementFamily(BCElement) == 1 ) CYCLE308Surface = .FALSE.309Bedrock = .FALSE.310Surface = GetLogical( BC, 'Shape Surface', GotIt)311Bedrock = GetLogical( BC, 'Shape Bedrock', GotIt)312IF (Surface) THEN313n = BCElement % Type % NumberOfNodes314CALL GetElementNodes( Nodes , BCElement )315DO i = 1,n316j = BCElement % NodeIndexes( i )317Bu = BCElement % Type % NodeU(i)318Bv = 0.0D0319Normal = NormalVector(BCElement, Nodes, Bu, Bv, .TRUE.)320TempS = 0321WHERE (NodesOnSurface==j) TempS = 1322k = MAXLOC(TempS, dim=1)323ts(1,k) = ts(1,k) + Normal(2)324ts(2,k) = ts(2,k) - Normal(1)325xs(k) = Model % Nodes % x(j)326zs(k) = Model % Nodes % y(j)327END DO328ELSE IF(Bedrock) THEN329n = BCElement % Type % NumberOfNodes330DO i = 1,n331j = BCElement % NodeIndexes( i )332TempB = 0333WHERE (NodesOnBed==j) TempB = 1334k = MAXLOC(TempB, dim=1)335xb(k) = Model % Nodes % x(j)336zb(k) = Model % Nodes % y(j)337END DO338END IF339END DO340341DO i=1, Ns342ts(:,i) = ts(:,i) / SQRT(SUM(ts(:,i)**2.0))343END DO344Model % CurrentElement => CurElement345346!-----------------------------------347! Construct the spline interpolation348!-----------------------------------349CALL CubicSpline(Ns,xs,zs,z2s)350CALL CubicSpline(Nb,xb,zb,z2b)351CALL CubicSpline(Ns,xs,ts(1,:),ts2x)352CALL CubicSpline(Ns,xs,ts(2,:),ts2y)353IF (Computed) CALL CubicSpline(Ns,xs,para,para2)354355ENDIF ! new dt356357358BodyForce => GetBodyForce()359CurElement => Model % CurrentElement360n = CurElement % Type % NumberOfNodes361!-----------------------362! Interpolate for that x363!-----------------------364x = Model % Nodes % x ( nodenumber)365IF (Computed) THEN366z2s_p => z2s367z2b_p => z2b368H = InterpolateCurve(xs,zs,x,z2s_p) - InterpolateCurve(xb,zb,x,z2b_p)369IF (Parabola) THEN370para2_p => para2371afactor = InterpolateCurve(xs,para,x,para2_p)372IF ((H>0.0).AND.(afactor>0.0)) THEN373w = 1.0/SQRT(H*afactor)374f = 0.0_dp375DO i=1, np376f = f + ATAN(ap(i)*w**i)377END DO378f = 2.0*f/(np*pi)379ELSE380f = 1.0381END IF382ELSE IF (Rectangle) THEN383para2_p => para2384width = InterpolateCurve(xs,para,x,para2_p)385IF (H>0.0) THEN386w = width / (2.0*H)387f = 0.0_dp388DO i=1, nr389f = f + ATAN(ar(i)*w**i)390END DO391f = 2.0*f/(nr*pi)392ELSE393f = 1.0394END IF395END IF396ELSE397!------------------------------------398! Get the Shape factor for that nodes399!------------------------------------400auxReal(1:n) = GetReal( BodyForce, &401'Shape Factor', GotIt )402DO i=1, n403j = CurElement % NodeIndexes (i)404IF (nodenumber == j) EXIT405END DO406f = auxReal(i)407END IF408409ts2x_p => ts2x410ts2y_p => ts2y411tangent(1) = InterpolateCurve(xs,ts(1,:),x,ts2x_p)412tangent(2) = InterpolateCurve(xs,ts(2,:),x,ts2y_p)413tangent = tangent / SQRT(SUM(tangent**2.0))414415gi = g(axis) - (1.0 - f) * SUM(g*tangent) * tangent(axis)416417418419END FUNCTION ShapeFactorGravity420421422423