Program drain_m c Vaughan Voller c University of Minnesota c October 2002 c program for calculating drainage from an edge drain c drain program implicit none Integer ktime, Kit,ntime Integer I integer subbase !material index of subbase Integer Tri(2999,0:3) Integer Sup(1599,0:8) Integer Bound(0:150) Integer props(1599,8) Integer Ntri Integer Nodes Real Ctri(2999,3,4) Real Coef(1599,0:8) Real Area(2999) Real Narea(1599) Real NodeA(1599,0:8) Real Cp(1599) Real Source(1599) Real Bval(150),Bcoef(150) Real P(1599) Real Pstar(1599) Real F(1599) Real Fold(1599) Real M_D(1599) !nodal mostures in granular base Real maxF Real X(1599) Real Y(1599) Real fsum,fsumold !tot. moisture in gran. base Real fsumin !initial moisture in Real flowout !flow into drain Real mprops(5,10) Real pinit Real delt Call Readit (Nodes,Ntri,Bound,Bval,Bcoef,Sup,Tri,X,Y,mprops, & ntime,delt,pinit,subbase) Call TriCoef(Ntri,Ctri,Tri,Area,Narea,X,Y) Call Nodeprops(Nodes,Ntri,Tri,Area,Narea,props,NodeA) Call initial(Nodes,F,Fold,M_D,P,Pstar,pinit) Call Moist(Ntri,Tri,Area,Narea,P,F,mprops) Call Moist(Ntri,Tri,Area,Narea,P,Fold,mprops) C initial moisture fsum=0 Call Dmoist(Ntri,Tri,Area,P,M_D,mprops,subbase) Do I=1,Nodes fsum=fsum + M_D(I) enddo fsumin=fsum open(4,file='dtime.dat') write(4,*) 0,fsum/fsumin,fsum,0,0 print *, 'PROGRAM RUNNING please wait' print *, print *,'time(sec) -- degree of Saturation-cm^2 moist gran base &convergence~e-4' print *, ktime*delt,fsum/fsumin,fsum,' ',maxF Do ktime = 1,ntime Do Kit = 1,50 Call Coeficient(Ntri,delt,Ctri,Sup,Tri,Cp,Source,Area,Narea, & Bound,Bval,Bcoef,Coef,F,Fold,P,mprops) Call Solve(Nodes,Sup,Source,Coef,Pstar,Bound,Bcoef,flowout) Call AdjustF(Nodes,F,P,Pstar,Cp,props,mprops,NodeA,maxF) Call Clean(Nodes,Sup,Source,Cp,Coef,M_D) If (maxF.lt.0.00005.and.kit.gt.3) goto 10 enddo 10 continue c Drain Moisture fsumold=fsum fsum=0 Call Dmoist(Ntri,Tri,Area,P,M_D,mprops,subbase) Do I=1,Nodes fsum=fsum + M_D(I) enddo print *, ktime*delt,fsum/fsumin,fsum,' ',maxF write(4,*) ktime *delt,fsum/fsumin,fsum,flowout, & fsumold-fsum-flowout c massbal write(4,*) ktime * delt,fsum-fsumin,flowout Call Swap(Nodes,F,Fold) enddo 11 close(4) c Trench moisture for writeup Call Trench(Nodes,X,Y,P,mprops) print *, "Program Sucesfully Terminated" pause stop end c-------------------------- Subroutine Readit(Nodes,Ntri,Bound,Bval,Bcoef, & Sup,Tri,X,Y,mprops,ntime,delt,pinit,subbase) Integer I,J Integer Tri(2999,0:3) Integer Sup(1599,0:8) Integer Bound(0:150) Integer Ntri Integer Nodes Integer nmats Integer subbase Integer ntime Real Bval(150),Bcoef(150) Real X(1599) Real Y(1599) Real mprops(5,10) Real pinit Real delt open(3,file='drainin.dat') read(3,*) Nodes,Ntri do I=1,Nodes read(3,*) Sup(I,0) read(3,*) (Sup(I,J),J=1,Sup(I,0)) enddo do I=1,Ntri read(3,*) (Tri(I,J),J=0,3) enddo do I=1,Nodes read(3,*) X(i),Y(i) enddo read(3,*) Bound(0) read(3,*) (Bound(J),J=1,Bound(0)) read(3,*) (Bcoef(j),J=1,Bound(0)) read(3,*) (Bval(j),J=1,Bound(0)) read (3,*) nmats do i=1,nmats read(3,*) (mprops(i,j),j=1,6) enddo read(3,*) subbase read(3,*) ntime read(3,*) delt read(3,*) pinit return end c---------------------------------- Subroutine TriCoef(Ntri,Ctri,Tri,Area,Narea,X,Y) Integer Tri(2999,0:3) Integer Ntri Real Ctri(2999,3,4) Real Area(2999) Real Narea(1599) Real X(1599) Real Y(1599) Real XT(3) Real YT(3) Integer I,J Integer Nod(3) real SFX1 real SFX2 real SFX3 real SFY1 real SFY2 real SFY3 real DELX real DELY Do I=1,Ntri Do J=1,3 Nod(J)=Tri(I, J) XT(J)=X(Nod(J)) YT(J)=Y(Nod(J)) enddo Area(I) = (XT(2)*YT(3)-XT(3)*YT(2)-XT(1)*(YT(3)-YT(2))+ & YT(1)*(XT(3)-XT(2))) /2. C Nodal Areas DoJ=1,3 Narea(Nod(J)) = Narea(Nod(J))+Area(I)/3.0 enddo C Derivatives of shape function SFX1 = (YT(2) - YT(3)) / (2*Area(I)) SFX2 = (YT(3) - YT(1)) / (2*Area(I)) SFX3 = (YT(1) - YT(2)) / (2*Area(I)) SFY1 = (XT(3) - XT(2)) / (2*Area(I)) SFY2 = (XT(1) - XT(3)) / (2*Area(I)) SFY3 = (XT(2) - XT(1)) / (2*Area(I)) C Length of bisector 1 C Mid point of element - mid point of side 1-2 DELX = (2*XT(3) - XT(1) - XT(2))/6. DELY = (2*YT(3) - YT(1) - YT(2))/6. Ctri(I, 1, 1) = SFX1 * DELY - SFY1 * DELX Ctri(I, 1, 2) = SFX2 * DELY - SFY2 * DELX Ctri(I, 1, 3) = SFX3 * DELY - SFY3 * DELX Ctri(I, 1, 4) = -DELX C Length of bisector 2 C Mid point of element - mid point of side 2-3 DELX = (2*XT(1) - XT(2) - XT(3))/6. DELY = (2*YT(1) - YT(2) - YT(3))/6. Ctri(I, 2, 1) = SFX1 * DELY - SFY1 * DELX Ctri(I, 2, 2) = SFX2 * DELY - SFY2 * DELX Ctri(I, 2, 3) = SFX3 * DELY - SFY3 * DELX Ctri(I, 2, 4) = -DELX C Length of bisector 3 C Mid point of element - mid point of side 3-1 DELX = (2*XT(2) - XT(1) - XT(3))/6. DELY = (2*YT(2) - YT(1) - YT(3))/6. Ctri(I, 3, 1) = SFX1 * DELY - SFY1 * DELX Ctri(I, 3, 2) = SFX2 * DELY - SFY2 * DELX Ctri(I, 3, 3) = SFX3 * DELY - SFY3 * DELX Ctri(I, 3, 4) = -DELX enddo return end c------------------------------------------------ Subroutine Nodeprops(Nodes,Ntri,Tri,Area,Narea,props,NodeA) Integer Tri(2999,0:3) Integer props(1599,8) Integer Ntri Integer Nodes Real Area(2999) Real Narea(1599) Real NodeA(1599,0:8) Integer I,K,J logical Tricon Do I = 1,Nodes Do K = 1,Ntri Tricon = .False. Do J = 1,3 If(I.eq.Tri(K, J)) Tricon = .True. enddo If(Tricon) Then NodeA(I, 0) = NodeA(I, 0) + 1 NodeA(I, NodeA(I, 0)) = (Area(K)/3.) / Narea(I) props(I, NodeA(I, 0)) = Tri(K, 0) endif enddo enddo return end c---------------------------------------------------- Subroutine initial(Nodes,F,Fold,M_D,P,Pstar,pinit) Integer I Integer Nodes real P(1599) real Pstar(1599) real F(1599) real Fold(1599) real M_D(1599) real pinit Do I = 1,Nodes P(I) = pinit Pstar(I) = pinit F(i)=0.0 Fold(i)=0.0 M_D(i)=0.0 enddo return end c---------------------------------------------------- Subroutine Dmoist(Ntri,Tri,Area,P,M_D,mprops,subbase) Integer Tri(2999,0:3) Integer Ntri Real Area(2999) Real P(1599) Real M_D(1599) Real mprops(5,10) Integer I,J Integer Nod(3) Integer prop Integer subbase Do I = 1,Ntri prop = Tri(I, 0) if(prop.ne.subbase) then Do J = 1,3 Nod(J) = Tri(I, J) M_D(Nod(J))=M_D(Nod(J))+(FNM(P(Nod(J)),prop,mprops)*Area(I)/3.) enddo endif enddo return end c-------------------------------------------- Subroutine Moist(Ntri,Tri,Area,Narea,P,F,mprops) Integer Tri(2999,0:3) Integer Ntri Real Area(2999) Real Narea(1599) Real P(1599) Real F(1599) Real mprops(5,10) Integer I,J Integer Nod(3) Integer prop Do I = 1,Ntri prop = Tri(I, 0) Do J = 1,3 Nod(J) = Tri(I, J) F(Nod(J))=F(Nod(J))+(FNM(P(Nod(J)),prop,mprops)*Area(I)/3.) & /Narea(Nod(J)) enddo enddo return end c-------------------------------------------- Subroutine Coeficient(Ntri,delt,Ctri,Sup,Tri,Cp,Source,Area, & Narea,Bound,Bval,Bcoef,Coef,F,Fold,P,mprops) Integer Tri(2999,0:3) Integer Sup(1599,0:8) Integer Bound(0:150) Integer Ntri Real Ctri(2999,3,4) Real Coef(1599,0:8) Real Area(2999) Real Narea(1599) Real Cp(1599) Real Source(1599) Real Bval(150) real Bcoef(150) Real F(1599) real P(1599) Real Fold(1599) Real mprops(5,10) Real delt Integer I, J Integer Npos Integer Nod(3) c Conductivities real K12 real K23 real K31 real Kave c Specific Moisture real C(3) c property integer prop Do I = 1,Ntri prop = Tri(I, 0) Do J = 1,3 Nod(J) = Tri(I, J) C(J) = FNC(P(Nod(J)),prop,mprops) enddo K12 = delt * FNK(P(Nod(1)), P(Nod(2)), prop,mprops) K23 = delt * FNK(P(Nod(2)), P(Nod(3)), prop,mprops) K31 = delt * FNK(P(Nod(3)), P(Nod(1)), prop,mprops) c assumming TRAP integration Kave = (K12 + K23 + K31)/3. c Contributions to node 1 Do J = 1,Sup(Nod(1), 0) If(Nod(2).eq.Sup(Nod(1), J)) Npos = J enddo Coef(Nod(1),Npos)=Coef(Nod(1),Npos)+K12*(Ctri(I,1,2)-Ctri(I,3,2)) Coef(Nod(1),0)=Coef(Nod(1),0)+K12*(Ctri(I,1,2)-Ctri(I,3,2)) Do J = 1,Sup(Nod(1), 0) If (Nod(3).eq.Sup(Nod(1), J)) Npos = J enddo Coef(Nod(1),Npos)=Coef(Nod(1),Npos)+K31*(Ctri(I,1,3)-Ctri(I,3,3)) Coef(Nod(1),0)=Coef(Nod(1),0)+K31*(Ctri(I,1,3)-Ctri(I,3,3)) Source(Nod(1)) =Source(Nod(1))+Kave*(Ctri(I,1,4)-Ctri(I,3,4)) c Node 2 Do J = 1,Sup(Nod(2), 0) If (Nod(1).eq.Sup(Nod(2), J)) Npos = J enddo Coef(Nod(2),Npos)=Coef(Nod(2),Npos)+K12*(Ctri(I,2,1)-Ctri(I,1,1)) Coef(Nod(2),0)=Coef(Nod(2),0)+K12*(Ctri(I,2,1)-Ctri(I, 1, 1)) Do J = 1,Sup(Nod(2), 0) If (Nod(3).eq.Sup(Nod(2), J)) Npos = J enddo Coef(Nod(2),Npos)=Coef(Nod(2), Npos)+K23*(Ctri(I,2,3)-Ctri(I,1,3)) Coef(Nod(2),0)=Coef(Nod(2),0)+K23*(Ctri(I,2,3)-Ctri(I,1,3)) Source(Nod(2))=Source(Nod(2))+Kave*(Ctri(I,2,4)-Ctri(I,1,4)) c Node 3 Do J = 1,Sup(Nod(3), 0) If (Nod(1).eq.Sup(Nod(3), J)) Npos = J enddo Coef(Nod(3),Npos)=Coef(Nod(3),Npos)+K31*(Ctri(I,3,1)-Ctri(I,2,1)) Coef(Nod(3), 0)=Coef(Nod(3),0)+K31*(Ctri(I,3,1)-Ctri(I,2,1)) Do J = 1,Sup(Nod(3), 0) If (Nod(2).eq.Sup(Nod(3), J)) Npos = J enddo Coef(Nod(3),Npos)=Coef(Nod(3),Npos)+K23*(Ctri(I,3,2)-Ctri(I,2,2)) Coef(Nod(3),0)=Coef(Nod(3),0)+K23*(Ctri(I,3,2)-Ctri(I,2,2)) Source(Nod(3))=Source(Nod(3))+Kave*(Ctri(I,3,4)-Ctri(I,2,4)) C Sources Do J = 1,3 Coef(Nod(J), 0) = Coef(Nod(J), 0) + C(J) * Area(I)/3. Source(Nod(J))=Source(Nod(J))+(Area(I)/3.)*(C(J)*P(Nod(J))+ & Fold(Nod(J)) - F(Nod(J))) Cp(Nod(J))=Cp(Nod(J))+C(J)*(Area(I)/3.)/Narea(Nod(J)) enddo enddo C update boundry coeficients Do I = 1,Bound(0) Coef(Bound(I), 0) =Coef(Bound(I),0)+Bcoef(I) Source(Bound(I)) = Source(Bound(I))+Bval(I) enddo return end c---------------------------------- Subroutine Solve(Nodes,Sup,Source,Coef,P,Bound,Bcoef,flowout) Integer Sup(1599,0:8) Integer Nodes Integer Bound(0:150) Real Coef(1599,0:8) Real Source(1599) Real P(1599) Real Bcoef(150) Integer K,I,J real RHS real flowout real flownode Do K = 1,50 Do I = 1,Nodes RHS = 0 Do J = 1,Sup(I, 0) RHS = RHS + Coef(I, J) * P(Sup(I, J)) enddo P(I) = P(I) + 1.0 * ((RHS + Source(I))/Coef(I, 0) - P(I)) enddo enddo c---- calculation of flow into drain ASSUMMES THAT p = 0 in drain c--- This will need modification to be a full review boundary flowout=0 do K=1,Bound(0) flownode=0 if (Bcoef(K).gt.1e19) then !danger recognize by force term I=Bound(K) do J=1,Sup(I,0) flownode=flownode+Coef(I,J)*P(Sup(I,J)) enddo flownode=flownode+Source(I) endif if (flownode.lt.0) Bcoef(K)=0.0 if (Bcoef(K).gt.1e19) flowout=flowout+flownode enddo return end c----------------------------------------------------- Subroutine AdjustF(Nodes,F,P,Pstar,Cp,props,mprops,NodeA,maxF) Integer props(1599,8) Integer Nodes Real NodeA(1599,0:8) Real Cp(1599) Real P(1599) real Pstar(1599) Real F(1599) Real mprops(5,10) Real maxF Real DelF Integer I,J,Kit real Pnode(8) real Pmax,Pmin,Pmid real FstarM,FstarL real ssearch maxF=0.0 Do I = 1,Nodes DelF= 0.25* Cp(I) * (Pstar(I) - P(I)) if(abs(DelF)/F(i).lt.0.025) then F(i)=F(i)+delF else f(i)=f(i)*(1+(delF/abs(delF))*0.025) endif if(abs(Cp(i)*(Pstar(i)-P(i))).gt.maxF) & maxF=abs(cp(i)*(Pstar(i)-P(i))) Pmax = -1000 Pmin = 1000 Do J = 1,NodeA(I, 0) Pnode(J) = Finv(F(I), props(I, J),mprops) If(Pnode(J).ge.Pmax) Pmax = Pnode(J) If(Pnode(J).le.Pmin) Pmin = Pnode(J) enddo If(Pmax.eq.Pmin) Then Pmid = Pmin Else FstarL = 0 Do J = 1,NodeA(I, 0) FstarL = FstarL + FNM(Pmin, props(I, J),mprops) * NodeA(I, J) enddo ssearch = (Pmax - Pmin)/2. Do Kit = 1,20 Pmid = Pmin + ssearch FstarM = 0 Do J = 1,NodeA(I, 0) FstarM = FstarM + FNM(Pmid, props(I, J),mprops) * NodeA(I, J) enddo If((FstarM-F(I))*(FstarL-F(I)).le.0) Then ssearch = -ssearch/2. FstarL = FstarM endif Pmin = Pmid enddo endif P(I) = P(I) + (Pmid - P(I)) enddo return end c--------------------------------------- Subroutine Clean(Nodes,Sup,Source,Cp,Coef,M_D) Integer Sup(1599,0:8) Integer Nodes Real Coef(1599,0:8) Real Cp(1599) Real Source(1599) Real M_D(1599) Integer I,J Do I = 1,Nodes Do J = 0,Sup(I, 0) Coef(I, J) = 0 enddo Source(I) = 0 Cp(I) = 0 M_D(I)=0 enddo return end c-------------------------------- Subroutine Swap(Nodes,F,Fold) Integer I,Nodes real F(1599),Fold(1599) Do I = 1,Nodes Fold(I) = F(I) enddo return end c-------------------------------------------------------- Subroutine Trench(Nodes,X,Y,P,mprops) Integer I Integer Nodes Real X(1599) Real Y(1599) Real P(1599) Real mprops(5,10) open(5,file='trench.dat') do I=1,Nodes if (X(I).ge.150.and.X(I).le.200) then if (Y(I).ge.-15.and.Y(I).le.15) then write(5,*) X(I),Y(I),FNM(P(I),2,mprops) endif endif enddo close(5) return end c-------------------------- Real Function FNK(P1,P2,prop,mprops) integer prop real mprops(5,10) real P1,P2 real fsat,fres,ksat,lamda real F1,F2 F1 = FNM(P1, prop,mprops) F2 = FNM(P2, prop,mprops) real K1,K2 lamda = mprops(prop,6) ksat = mprops(prop,5) ! 0.000098 fsat = mprops(prop,2) fres = mprops(prop,3) K1 = (F1 - fres) / (fsat - fres) If(K1.gt.1) K1 = 1 K1 = ksat * K1**(lamda) K2 = (F2 - fres) / (fsat - fres) If(K2.gt.1) K2 = 1 K2 = ksat * K2**(lamda) FNK = (K1 + K2) / 2.0 return end c ----------------------- real Function FNC(P, prop,mprops) real P Integer prop real Cval real satval real hd real lamda real fres real fsat real F real mprops(5,10) F = FNM(P,prop,mprops) lamda = mprops(prop,1) fres = mprops(prop,3) fsat = mprops(prop,2) hd = mprops(prop,4) satval = (F - fres) / (fsat - fres) Cval = (fsat - fres) * (-lamda / hd) * satval**(1 + 1 / lamda) If(satval.gt.1) Cval = 0.0001 FNC = Cval return end c-------------------------- real Function FNM(P,prop,mprops) integer prop real P real fval real hd real lamda real fres real fsat real fhd real mprops(5,10) lamda = mprops(prop,1) fres = mprops(prop,3) fsat = mprops(prop,2) hd = mprops(prop,4) ! fhd = mprops(prop,2)-mprops(prop,4)*0.0001 If (P.lt.hd) Then fval = (fsat - fres) * ((P / hd)**(-lamda)) + fres Else fval = 0.0001 * P + fhd endif FNM = fval return end c---------------------------------- real Function Finv(F, prop,mprops) integer prop real F real pval real hd real lamda real fres real fsat real fhd real mprops(5,10) lamda = mprops(prop,1) fres = mprops(prop,3) fsat = mprops(prop,2) hd = mprops(prop,4) ! fhd = mprops(prop,2)-mprops(prop,4)*0.0001 If (F.lt.fsat) Then pval = hd * ((F - fres) / (fsat - fres))**(-1 / lamda) Else pval = 10000*(F - fhd) End If Finv=pval return end c--------------------------------