Skip to content

Commit fcb4bfa

Browse files
authored
Merge pull request #6 from gaelforget/ImproveExchOpsPerformance
rewrite exchange methods and streamline operations to improve performance
2 parents 1c8c05e + 19865be commit fcb4bfa

File tree

6 files changed

+391
-651
lines changed

6 files changed

+391
-651
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "MeshArrays"
22
uuid = "28126448-9d44-11e8-08f5-e59c47736fcb"
33
authors = ["gaelforget <[email protected]>"]
4-
version = "0.1.3"
4+
version = "0.1.4"
55

66
[deps]
77
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"

src/MeshArrays.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ include("gcmfaces_convert.jl");
1212
include("gcmfaces_IO.jl");
1313
include("gcmfaces_demo.jl");
1414

15-
export gcmfaces, exchange, gradient, smooth, mask, fsize
15+
export gcmfaces, exchange, gradient, convergence, smooth, mask, fsize
1616
export GCMGridSpec, GCMGridLoad, GCMGridOnes
1717
export demo1, demo2
1818
#The following functions rely on grid specs; currently via global vars.

src/gcmfaces_calc.jl

+124-62
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,170 @@
11

2-
function gradient(fld)
2+
## gradient methods
33

4-
FLD=exchange(fld,1);
4+
function gradient(inFLD::gcmfaces)
5+
(dFLDdx, dFLDdy)=gradient(inFLD,true)
6+
return dFLDdx, dFLDdy
7+
end
8+
9+
function gradient(inFLD::gcmfaces,doDIV::Bool)
10+
11+
exFLD=exchange(inFLD,1)
12+
dFLDdx=gcmfaces(inFLD.nFaces,inFLD.grTopo)
13+
dFLDdy=gcmfaces(inFLD.nFaces,inFLD.grTopo)
14+
15+
for a=1:inFLD.nFaces;
16+
(s1,s2)=fsize(exFLD,a)
17+
tmpA=view(exFLD.f[a],2:s1-1,2:s2-1)
18+
tmpB=tmpA-view(exFLD.f[a],1:s1-2,2:s2-1)
19+
tmpC=tmpA-view(exFLD.f[a],2:s1-1,1:s2-2)
20+
if doDIV
21+
dFLDdx.f[a]=tmpB./MeshArrays.DXC.f[a]
22+
dFLDdy.f[a]=tmpC./MeshArrays.DYC.f[a]
23+
else
24+
dFLDdx.f[a]=tmpB
25+
dFLDdy.f[a]=tmpC
26+
end
27+
end
528

6-
dFLDdx=gcmfaces(fld.nFaces,fld.grTopo);
7-
dFLDdy=gcmfaces(fld.nFaces,fld.grTopo);
8-
for iFace=1:FLD.nFaces;
9-
tmpA=FLD.f[iFace][2:end-1,2:end-1];
10-
tmpB=FLD.f[iFace][1:end-2,2:end-1];
11-
dFLDdx.f[iFace]=(tmpA-tmpB)./MeshArrays.DXC.f[iFace];
12-
tmpA=FLD.f[iFace][2:end-1,2:end-1];
13-
tmpB=FLD.f[iFace][2:end-1,1:end-2];
14-
dFLDdy.f[iFace]=(tmpA-tmpB)./MeshArrays.DYC.f[iFace];
15-
end;
29+
return dFLDdx, dFLDdy
30+
end
31+
32+
function gradient(inFLD::gcmfaces,iDXC::gcmfaces,iDYC::gcmfaces)
1633

17-
return dFLDdx, dFLDdy
34+
exFLD=exchange(inFLD,1)
35+
dFLDdx=gcmfaces(inFLD.nFaces,inFLD.grTopo)
36+
dFLDdy=gcmfaces(inFLD.nFaces,inFLD.grTopo)
1837

38+
for a=1:inFLD.nFaces;
39+
(s1,s2)=fsize(exFLD,a)
40+
tmpA=view(exFLD.f[a],2:s1-1,2:s2-1)
41+
tmpB=tmpA-view(exFLD.f[a],1:s1-2,2:s2-1)
42+
tmpC=tmpA-view(exFLD.f[a],2:s1-1,1:s2-2)
43+
dFLDdx.f[a]=tmpB.*iDXC.f[a]
44+
dFLDdy.f[a]=tmpC.*iDYC.f[a]
1945
end
2046

21-
##
47+
return dFLDdx, dFLDdy
48+
end
49+
50+
## mask methods
2251

2352
function mask(fld::gcmfaces)
24-
fldmsk=mask(fld,(NaN,Inf,0.),NaN)
25-
return fldmsk
53+
fldmsk=mask(fld,NaN)
54+
return fldmsk
2655
end
2756

2857
function mask(fld::gcmfaces, val::Number)
29-
fldmsk=mask(fld,(NaN,Inf,0.),val)
58+
fldmsk=gcmfaces(fld.nFaces,fld.grTopo)
59+
for a=1:fld.nFaces
60+
tmp1=copy(fld.f[a])
61+
replace!(x -> !isfinite(x) ? val : x, tmp1 )
62+
fldmsk.f[a]=tmp1
63+
end
3064
return fldmsk
3165
end
3266

33-
function mask(fld::gcmfaces, cond::Number, val::Number)
34-
fldmsk=mask(fld,(cond,),val)
67+
function mask(fld::gcmfaces, val::Number, noval::Number)
68+
fldmsk=gcmfaces(fld.nFaces,fld.grTopo)
69+
for a=1:fld.nFaces
70+
tmp1=copy(fld.f[a])
71+
replace!(x -> x==noval ? val : x, tmp1 )
72+
fldmsk.f[a]=tmp1
73+
end
3574
return fldmsk
3675
end
3776

38-
function mask(fld::gcmfaces,cond::Tuple,val::Number)
77+
## convergence methods
3978

40-
fldmsk=gcmfaces(fld.nFaces,fld.grTopo);
79+
function convergence(uFLD::gcmfaces,vFLD::gcmfaces);
4180

42-
for iFace=1:fld.nFaces;
43-
tmp1=fld.f[iFace]
44-
for i=1:length(cond)
45-
isnan(cond[i]) ? tmp1[findall(isnan.(tmp1))] .= val : nothing
46-
isinf(cond[i]) ? tmp1[findall(isinf.(tmp1))] .= val : nothing
47-
isfinite(cond[i]) ? tmp1[findall(tmp1 .== cond[i])] .= val : nothing
48-
end
49-
fldmsk.f[iFace]=tmp1
50-
end
81+
#important note:
82+
# Normally uFLD, vFLD should not contain any NaN;
83+
# if otherwise then something this may be needed:
84+
# uFLD=mask(uFLD,0.0); vFLD=mask(vFLD,0.0);
5185

52-
return fldmsk
86+
CONV=gcmfaces(uFLD.nFaces,uFLD.grTopo)
5387

88+
(tmpU,tmpV)=exch_UV(uFLD,vFLD)
89+
for a=1:tmpU.nFaces
90+
(s1,s2)=fsize(uFLD,a)
91+
tmpU1=view(tmpU.f[a],1:s1,1:s2)
92+
tmpU2=view(tmpU.f[a],2:s1+1,1:s2)
93+
tmpV1=view(tmpV.f[a],1:s1,1:s2)
94+
tmpV2=view(tmpV.f[a],1:s1,2:s2+1)
95+
CONV.f[a]=tmpU1-tmpU2+tmpV1-tmpV2
5496
end
5597

56-
##
98+
return CONV
99+
end
100+
101+
## smooth function
102+
103+
function smooth(FLD::gcmfaces,DXCsm::gcmfaces,DYCsm::gcmfaces)
104+
105+
#important note:
106+
#input FLD should be land masked (NaN/1) by caller if needed
57107

58-
function smooth(fld::gcmfaces,DXCsm::gcmfaces,DYCsm::gcmfaces)
108+
#get land masks (NaN/1):
109+
mskC=fill(1.0,FLD) + 0.0 * mask(FLD)
110+
(mskW,mskS)=gradient(FLD,false)
111+
mskW=fill(1.0,FLD) + 0.0 * mask(mskW)
112+
mskS=fill(1.0,FLD) + 0.0 * mask(mskS)
59113

60-
#get land mask:
61-
msk=fill(1.,fld) + 0. * mask(fld,NaN);
114+
#replace NaN with 0. in FLD and land masks:
115+
FLD=mask(FLD,0.0)
116+
mskC=mask(mskC,0.0)
117+
mskW=mask(mskW,0.0)
118+
mskS=mask(mskS,0.0)
119+
120+
#get inverse grid spacing:
121+
iDXC=gcmfaces(FLD.nFaces,FLD.grTopo)
122+
iDYC=gcmfaces(FLD.nFaces,FLD.grTopo)
123+
for a=1:FLD.nFaces;
124+
iDXC.f[a]=1.0./MeshArrays.DXC.f[a]
125+
iDYC.f[a]=1.0./MeshArrays.DYC.f[a]
126+
end
62127

63128
#Before scaling the diffusive operator ...
64-
tmp0=DXCsm/MeshArrays.DXC;
65-
tmp0=mask(msk*tmp0,0.);
129+
tmp0=DXCsm*iDXC*mskW;
66130
tmp00=maximum(tmp0);
67-
tmp0=DYCsm/MeshArrays.DYC;
68-
tmp0=mask(msk*tmp0,0.);
131+
tmp0=DYCsm*iDYC*mskS;
69132
tmp00=max(tmp00,maximum(tmp0));
70133

71134
#... determine a suitable time period:
72135
nbt=ceil(1.1*2*tmp00^2);
73136
dt=1.;
74137
T=nbt*dt;
138+
#println("nbt="*"$nbt")
139+
140+
#diffusion operator times DYG / DXG:
141+
KuxFac=mskW*DXCsm*DXCsm/T/2.0*MeshArrays.DYG;
142+
KvyFac=mskS*DYCsm*DYCsm/T/2.0*MeshArrays.DXG;
75143

76-
#diffusion operator:
77-
Kux=DXCsm*DXCsm/T/2;
78-
Kvy=DYCsm*DYCsm/T/2;
144+
#time steping factor:
145+
dtFac=dt*mskC/MeshArrays.RAC;
79146

80147
#loop:
81148
for it=1:nbt
82-
(dTdxAtU,dTdyAtV)=gradient(fld);
83-
tmpU=dTdxAtU*Kux*MeshArrays.DYG;
84-
tmpV=dTdyAtV*Kvy*MeshArrays.DXG;
149+
(dTdxAtU,dTdyAtV)=gradient(FLD,iDXC,iDYC);
150+
tmpU=gcmfaces(FLD.nFaces,FLD.grTopo)
151+
tmpV=gcmfaces(FLD.nFaces,FLD.grTopo)
152+
for a=1:FLD.nFaces
153+
tmpU.f[a]=dTdxAtU.f[a].*KuxFac.f[a];
154+
tmpV.f[a]=dTdyAtV.f[a].*KvyFac.f[a];
155+
end
85156
tmpC=convergence(tmpU,tmpV);
86-
fld=fld-dt*msk*tmpC/MeshArrays.RAC;
157+
for a=1:FLD.nFaces
158+
FLD.f[a]=FLD.f[a]-dtFac.f[a].*tmpC.f[a];
159+
end
87160
end
88161

89-
return fld
162+
#Apply land mask (NaN/1) to end result:
163+
mskC=mask(mskC,NaN,0.0)
164+
FLD=mskC*FLD
165+
166+
return FLD
90167

91168
end
92169

93170
##
94-
95-
function convergence(fldU::gcmfaces,fldV::gcmfaces);
96-
97-
(tmpU,tmpV)=exch_UV(fldU,fldV);
98-
tmpU=mask(tmpU,NaN,0);
99-
tmpV=mask(tmpV,NaN,0);
100-
tmpC=gcmfaces(tmpU.nFaces,tmpU.grTopo);
101-
for iFace=1:tmpU.nFaces;
102-
tmp1=tmpU.f[iFace][1:end-1,:,:,:]-tmpU.f[iFace][2:end,:,:,:];
103-
tmp2=tmpV.f[iFace][:,1:end-1,:,:]-tmpV.f[iFace][:,2:end,:,:];
104-
tmpC.f[iFace]=dropdims(tmp1+tmp2,dims=(3,4));
105-
end;
106-
return tmpC
107-
108-
end

src/gcmfaces_demo.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ Rini=convert2gcmfaces(tmp1);
6363

6464
#apply land mask
6565
if ndims(MeshArrays.hFacC.f[1])>2
66-
tmp1=mask(view(MeshArrays.hFacC,:,:,1),NaN);
66+
tmp1=mask(view(MeshArrays.hFacC,:,:,1),NaN,0);
6767
else
68-
tmp1=mask(MeshArrays.hFacC,NaN);
68+
tmp1=mask(MeshArrays.hFacC,NaN,0);
6969
end
7070
msk=fill(1.,tmp1) + 0. *tmp1;
7171
Rini=msk*Rini;

0 commit comments

Comments
 (0)