gphys 1.5.6 → 1.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/ChangeLog +0 -7672
- data/bin/gpcut +12 -0
- data/bin/gpvect +88 -77
- data/bin/gpview +200 -103
- data/ext/numru/gphys/dim_op.c +336 -44
- data/ext/numru/gphys/ext_init.c +6 -0
- data/ext/numru/gphys/interpo.c +326 -3
- data/lib/numru/dclext.rb +78 -16
- data/lib/numru/ganalysis/beta_plane.rb +6 -4
- data/lib/numru/ganalysis/eof.rb +61 -41
- data/lib/numru/ganalysis/fitting.rb +86 -23
- data/lib/numru/ganalysis/histogram.rb +3 -3
- data/lib/numru/ganalysis/log_p.rb +20 -0
- data/lib/numru/ganalysis/lomb_scargle.rb +205 -0
- data/lib/numru/ganalysis/met_z.rb +132 -3
- data/lib/numru/ganalysis/narray_ext.rb +1 -1
- data/lib/numru/ganalysis/pde.rb +20 -1
- data/lib/numru/ganalysis/planet.rb +136 -1
- data/lib/numru/ganalysis/qg.rb +224 -3
- data/lib/numru/ggraph.rb +89 -18
- data/lib/numru/gphys/axis.rb +4 -2
- data/lib/numru/gphys/gphys_dim_op.rb +69 -6
- data/lib/numru/gphys/gphys_fft.rb +30 -0
- data/lib/numru/gphys/gphys_io_common.rb +2 -0
- data/lib/numru/gphys/grads_gridded.rb +77 -29
- data/lib/numru/gphys/grib.rb +2 -2
- data/lib/numru/gphys/grib_params.rb +3 -3
- data/lib/numru/gphys/interpolate.rb +153 -1
- data/lib/numru/gphys/varraycomposite.rb +7 -4
- data/lib/numru/gphys/version.rb +1 -1
- data/testdata/pres.jan.nc +0 -0
- metadata +6 -4
data/ext/numru/gphys/dim_op.c
CHANGED
@@ -30,6 +30,8 @@ enum bc_type {
|
|
30
30
|
#define ID3o(i,j,k) ((i) + (j)*n0 + (k)*n0*n1o)
|
31
31
|
#define ID3z(i,j,k) ((i) + (j)*n0 + (k)*n0*nz)
|
32
32
|
#define ID3c(i,j,k) ((i) + (j)*n0 + (k)*n0*nc)
|
33
|
+
#define ID3e(i,j,k,ni,nj,nk) (((i)%(ni)) + (j)*(ni) + ((k)%(nk))*(ni)*(nj))
|
34
|
+
// ID3e: covers 1D case (if ni==1 or nk==1, i or k is neglected by %)
|
33
35
|
#define ID2(i,j) ((i) + (j)*n0)
|
34
36
|
#define ID5(i,j,k,l,m) ((i) + (j)*ni + (k)*ni*nd1 + (l)*ni*nd1*no1 + (m)*ni*nd1*no1*nd2)
|
35
37
|
#define NMax(i,j) ( (i) >= (j) ? (i) : (j) )
|
@@ -853,13 +855,13 @@ bin_mean_sum(int argc, VALUE *argv, VALUE self, int mean)
|
|
853
855
|
static VALUE
|
854
856
|
bin_mean(int argc, VALUE *argv, VALUE self)
|
855
857
|
{
|
856
|
-
bin_mean_sum(argc, argv, self, 1);
|
858
|
+
return bin_mean_sum(argc, argv, self, 1);
|
857
859
|
}
|
858
860
|
|
859
861
|
static VALUE
|
860
862
|
bin_sum(int argc, VALUE *argv, VALUE self)
|
861
863
|
{
|
862
|
-
bin_mean_sum(argc, argv, self, 0);
|
864
|
+
return bin_mean_sum(argc, argv, self, 0);
|
863
865
|
}
|
864
866
|
|
865
867
|
|
@@ -1000,36 +1002,44 @@ is simply when w is z itself, which is exploited in implementation.
|
|
1000
1002
|
|
1001
1003
|
*/
|
1002
1004
|
static VALUE
|
1003
|
-
cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
1005
|
+
cell_integ_irreg(obj, f, mask, z, zdim, nzbound, ccell, w)
|
1004
1006
|
VALUE obj;
|
1005
1007
|
VALUE f; // [NArray] multi-D data to be integrated
|
1006
|
-
VALUE
|
1007
|
-
|
1008
|
+
VALUE mask; // [nil, or NArray] if NArray, mask of f
|
1009
|
+
VALUE z; // [NArray] 1D or multi-D coordinate values of f's grid
|
1010
|
+
// (if 1D, its length must be f's along zdim;
|
1011
|
+
// if multi-D z.shape must be equal to f.shape).
|
1012
|
+
// integration is always along z (whether or not w is given)
|
1008
1013
|
VALUE zdim; // [Integer] dimension of f along which to integrate
|
1009
1014
|
VALUE nzbound; // [nil, or NArray(integer) with rank 1 smaller than f's]
|
1010
1015
|
// Length of the actual z dim for each column (data must
|
1011
1016
|
// be packed from the beginning of z dim; 0...nzbound[j,l]).
|
1012
1017
|
// If nil, the entire column is assumed valid;
|
1013
|
-
VALUE ccell; // [NArray] 1D grid to sample the result.
|
1014
|
-
//
|
1018
|
+
VALUE ccell; // [NArray] 1D grid to sample the result.
|
1019
|
+
// (if multi-D, its shape except along zdim must be f's);
|
1020
|
+
// It is the z coordinate if w is nil;
|
1021
|
+
// if w is given, it's a w grid.
|
1015
1022
|
VALUE w; // [nil or NArray] alternative grid point values to express
|
1016
1023
|
// the result as a function of w rather than z (special case)
|
1017
1024
|
// (e.g. z: pressure/g; w: potential temperature)
|
1018
1025
|
{
|
1019
1026
|
struct NARRAY *na;
|
1020
|
-
int rank, zd, d;
|
1027
|
+
int rank, zd, d, with_mask;
|
1021
1028
|
na_shape_t *shape;
|
1022
1029
|
na_shape_t n0, nz, n2, nzw;
|
1030
|
+
na_shape_t n0z, n2z, n0w, n2w, n0c, n2c;
|
1023
1031
|
na_shape_t *oshape, nc;
|
1024
1032
|
VALUE F; // the result: \int f dz
|
1025
1033
|
double *fv, *zv, *wc, *wv, *Fv;
|
1026
1034
|
int32_t *nzbd;
|
1035
|
+
u_int8_t *msk;
|
1027
1036
|
na_shape_t j, k, l, m; // k: index of z (orig); m: index of ccell
|
1028
1037
|
double fa, fb, dz, wa, wb, wac, wbc, a, b, fi;
|
1029
1038
|
|
1030
1039
|
// cast to ensure pointer types
|
1031
1040
|
|
1032
1041
|
if(!IsNArray(f)) rb_raise(rb_eArgError, "f is not a NArray");
|
1042
|
+
if(mask!=Qnil && !IsNArray(mask)) rb_raise(rb_eArgError, "mask is must be nil or a NArray");
|
1033
1043
|
if(!IsNArray(z)) rb_raise(rb_eArgError, "z is not a NArray");
|
1034
1044
|
if(!IsNArray(ccell)) rb_raise(rb_eArgError, "ccell is not a NArray");
|
1035
1045
|
if(w!=Qnil && !IsNArray(w)) rb_raise(rb_eArgError, "w is must be nil or a NArray");
|
@@ -1043,9 +1053,6 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1043
1053
|
// read & check the shapes
|
1044
1054
|
|
1045
1055
|
rank = NA_RANK(f);
|
1046
|
-
if ( NA_RANK(z) != rank ){
|
1047
|
-
rb_raise(rb_eArgError, "f and z must have the same shape");
|
1048
|
-
}
|
1049
1056
|
if ( nzbound != Qnil && NA_RANK(nzbound) != rank-1 ){
|
1050
1057
|
rb_raise(rb_eArgError, "rank of nzbound must be 1 smaller than f's");
|
1051
1058
|
}
|
@@ -1068,17 +1075,61 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1068
1075
|
n2 *= shape[d];
|
1069
1076
|
}
|
1070
1077
|
|
1071
|
-
if
|
1072
|
-
|
1078
|
+
if(mask==Qnil) {
|
1079
|
+
with_mask = 0;
|
1080
|
+
msk = NULL;
|
1081
|
+
} else {
|
1082
|
+
with_mask = 1;
|
1083
|
+
if (NA_TOTAL(mask) != n0*nz*n2){
|
1084
|
+
rb_raise(rb_eArgError, "lengths of f and mask must agree");
|
1085
|
+
}
|
1086
|
+
GetNArray(mask, na);
|
1087
|
+
msk = (u_int8_t *)NA_PTR(na, 0);
|
1073
1088
|
}
|
1089
|
+
|
1090
|
+
if ( NA_RANK(z) == rank ){
|
1091
|
+
if (NA_TOTAL(z) != n0*nz*n2){
|
1092
|
+
rb_raise(rb_eArgError, "lengths of f and z must agree (if multiD)");
|
1093
|
+
}
|
1094
|
+
n0z = n0;
|
1095
|
+
n2z = n2;
|
1096
|
+
} else if (NA_RANK(z) == 1) {
|
1097
|
+
if (NA_TOTAL(z) != nz){
|
1098
|
+
rb_raise(rb_eArgError, "lengths of z must be nz (if 1D)");
|
1099
|
+
}
|
1100
|
+
n0z = 1;
|
1101
|
+
n2z = 1;
|
1102
|
+
} else {
|
1103
|
+
rb_raise(rb_eArgError, "z must have the same rank with f or be 1D");
|
1104
|
+
}
|
1105
|
+
|
1074
1106
|
if (nzbound != Qnil && NA_TOTAL(nzbound) != n0*n2){
|
1075
1107
|
rb_raise(rb_eArgError, "shapes of f and nzbound are incompatible");
|
1076
1108
|
}
|
1077
1109
|
|
1078
1110
|
// prepare the output array; assign pointers
|
1079
1111
|
|
1080
|
-
if ( NA_RANK(ccell)
|
1081
|
-
|
1112
|
+
if ( NA_RANK(ccell) == 1 ){
|
1113
|
+
nc = NA_TOTAL(ccell);
|
1114
|
+
n0c = 1;
|
1115
|
+
n2c = 1;
|
1116
|
+
} else if (NA_RANK(ccell) == rank) {
|
1117
|
+
GetNArray(ccell, na);
|
1118
|
+
shape = na->shape;
|
1119
|
+
for (d=0, n0c=1 ; d<zd ; d++){
|
1120
|
+
n0c *= shape[d];
|
1121
|
+
}
|
1122
|
+
nc = shape[zd];
|
1123
|
+
for (d=zd+1, n2c=1 ; d<rank ; d++){
|
1124
|
+
n2c *= shape[d];
|
1125
|
+
}
|
1126
|
+
if (n0c != n0) rb_raise(rb_eArgError,
|
1127
|
+
"shape miss match btwn f and ccell (case 0)");
|
1128
|
+
if (n2c != n2) rb_raise(rb_eArgError,
|
1129
|
+
"shape miss match btwn f and ccell (case 2)");
|
1130
|
+
} else {
|
1131
|
+
rb_raise(rb_eArgError, "ccell is must be 1D or f.rank");
|
1132
|
+
}
|
1082
1133
|
oshape = ALLOCA_N(na_shape_t, rank);
|
1083
1134
|
for (d=0; d<rank ; d++){
|
1084
1135
|
if (d != zd){
|
@@ -1105,15 +1156,32 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1105
1156
|
|
1106
1157
|
GetNArray(ccell, na);
|
1107
1158
|
wc = (double *)NA_PTR(na, 0);
|
1108
|
-
if (wc[0] > wc[nc-1]){
|
1159
|
+
if (wc[ID3e(0,0,0,n0c,nc,n2c)] > wc[ID3e(0,nc-1,0,n0c,nc,n2c)]){
|
1109
1160
|
rb_raise(rb_eArgError, "ccell must be alined in the increasing order");
|
1110
1161
|
}
|
1111
1162
|
|
1112
1163
|
if(w != Qnil){
|
1113
1164
|
GetNArray(w, na);
|
1114
1165
|
wv = (double *)NA_PTR(na, 0);
|
1166
|
+
if ( NA_RANK(w) == rank ){
|
1167
|
+
if (NA_TOTAL(w) != n0*nz*n2){
|
1168
|
+
rb_raise(rb_eArgError, "lengths of f and w must agree (if multiD)");
|
1169
|
+
}
|
1170
|
+
n0w = n0;
|
1171
|
+
n2w = n2;
|
1172
|
+
} else if (NA_RANK(w) == 1) {
|
1173
|
+
if (NA_TOTAL(w) != nz){
|
1174
|
+
rb_raise(rb_eArgError, "lengths of z must be nz (if 1D)");
|
1175
|
+
}
|
1176
|
+
n0w = 1;
|
1177
|
+
n2w = 1;
|
1178
|
+
} else {
|
1179
|
+
rb_raise(rb_eArgError, "z must have the same rank with f or be 1D");
|
1180
|
+
}
|
1115
1181
|
} else {
|
1116
1182
|
wv = zv;
|
1183
|
+
n0w = n0z;
|
1184
|
+
n2w = n2z;
|
1117
1185
|
}
|
1118
1186
|
|
1119
1187
|
// main loop
|
@@ -1130,24 +1198,27 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1130
1198
|
m=0; // m: index of the new cooridnate
|
1131
1199
|
for (k=0; k<nzw-1; k++){
|
1132
1200
|
// set the trapezoid
|
1133
|
-
if (wv[
|
1134
|
-
wa = wv[
|
1135
|
-
wb = wv[
|
1201
|
+
if (wv[ID3e(j,k,l,n0w,nz,n2w)] < wv[ID3e(j,k+1,l,n0w,nz,n2w)]) {
|
1202
|
+
wa = wv[ID3e(j,k,l,n0w,nz,n2w)]; // left/lower end along w
|
1203
|
+
wb = wv[ID3e(j,k+1,l,n0w,nz,n2w)]; //right/upper end along w
|
1136
1204
|
fa = fv[ID3z(j,k,l)]; // at the left end
|
1137
1205
|
fb = fv[ID3z(j,k+1,l)]; // at the right end
|
1138
1206
|
} else {
|
1139
|
-
wa = wv[
|
1140
|
-
wb = wv[
|
1207
|
+
wa = wv[ID3e(j,k+1,l,n0w,nz,n2w)]; // left/lower end along w
|
1208
|
+
wb = wv[ID3e(j,k,l,n0w,nz,n2w)]; //right/upper end along w
|
1141
1209
|
fa = fv[ID3z(j,k+1,l)]; // at the left end
|
1142
1210
|
fb = fv[ID3z(j,k,l)]; // at the right end
|
1143
1211
|
}
|
1144
|
-
|
1212
|
+
if ( with_mask && (!msk[ID3z(j,k,l)] || !msk[ID3z(j,k+1,l)]) ) {
|
1213
|
+
fa = fb = 0.0;
|
1214
|
+
}
|
1215
|
+
dz = fabs(zv[ID3e(j,k+1,l,n0z,nz,n2z)]-zv[ID3e(j,k,l,n0z,nz,n2z)]);
|
1145
1216
|
|
1146
1217
|
// find the right next grid point to wa (left end)
|
1147
|
-
if (wa < wc[m]){
|
1148
|
-
while( m>0 && wa < wc[m-1] ){ m--; }
|
1218
|
+
if (wa < wc[ID3e(j,m,l,n0c,nc,n2c)]){
|
1219
|
+
while( m>0 && wa < wc[ID3e(j,m-1,l,n0c,nc,n2c)] ){ m--; }
|
1149
1220
|
} else {
|
1150
|
-
while( wa >= wc[m] && m<nc ){ m++; }
|
1221
|
+
while( wa >= wc[ID3e(j,m,l,n0c,nc,n2c)] && m<nc ){ m++; }
|
1151
1222
|
// m can be nc, meaning the entire trapezoid is outside
|
1152
1223
|
}
|
1153
1224
|
|
@@ -1156,7 +1227,7 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1156
1227
|
wac = wa; // left end of the current bin
|
1157
1228
|
while(1){
|
1158
1229
|
//wbc = (wb<=wc[m]) ? wb : wc[m]; // current right end
|
1159
|
-
wbc = fmin(wb, wc[m]);
|
1230
|
+
wbc = fmin(wb, wc[ID3e(j,m,l,n0c,nc,n2c)]);
|
1160
1231
|
|
1161
1232
|
// do the integration
|
1162
1233
|
if (wb != wa){
|
@@ -1168,8 +1239,8 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1168
1239
|
}
|
1169
1240
|
// ^ f value at (a+b)/2 ^ width
|
1170
1241
|
Fv[ID3c(j,m,l)] += fi;
|
1171
|
-
if ( wb <= wc[m] || m == nc-1 ) break;
|
1172
|
-
wac = wc[m];
|
1242
|
+
if ( wb <= wc[ID3e(j,m,l,n0c,nc,n2c)] || m == nc-1 ) break;
|
1243
|
+
wac = wc[ID3e(j,m,l,n0c,nc,n2c)];
|
1173
1244
|
m++;
|
1174
1245
|
}
|
1175
1246
|
} else {
|
@@ -1189,8 +1260,9 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1189
1260
|
axis. -- This method acutually uses cell_integ_irreg and make sumation.
|
1190
1261
|
*/
|
1191
1262
|
static VALUE
|
1192
|
-
cum_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
1263
|
+
cum_integ_irreg(obj, f, mask, z, zdim, nzbound, ccell, w)
|
1193
1264
|
VALUE obj;
|
1265
|
+
VALUE mask; // [nil, or NArray] if NArray, mask of f
|
1194
1266
|
VALUE f;
|
1195
1267
|
VALUE z;
|
1196
1268
|
VALUE zdim;
|
@@ -1200,7 +1272,7 @@ cum_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1200
1272
|
{
|
1201
1273
|
VALUE F;
|
1202
1274
|
|
1203
|
-
F = cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w);
|
1275
|
+
F = cell_integ_irreg(obj, f, mask, z, zdim, nzbound, ccell, w);
|
1204
1276
|
cum_sum_dfloat_bang(obj, F, zdim);
|
1205
1277
|
return F;
|
1206
1278
|
}
|
@@ -1233,7 +1305,7 @@ cum_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
|
|
1233
1305
|
|
1234
1306
|
*/
|
1235
1307
|
static VALUE
|
1236
|
-
cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
1308
|
+
cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb, misval)
|
1237
1309
|
VALUE obj;
|
1238
1310
|
VALUE f; // [NArray] multi-D data
|
1239
1311
|
VALUE zdim; // [Integer] dimension of zcrd in f
|
@@ -1241,15 +1313,17 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1241
1313
|
VALUE upper; // true/false to cap the upper/lower side (with z)
|
1242
1314
|
VALUE zb; // [NArray] the "surface" z; zb.rank must be f.rank-1
|
1243
1315
|
VALUE fb; // [nil or NArray] the f value at surface (zb.shape==fb.shape)
|
1316
|
+
VALUE misval; // [nil or Float] if Float, missing value of f
|
1244
1317
|
{
|
1245
1318
|
VALUE fe; // [NArray] return value, extended f by fb
|
1246
1319
|
VALUE ze; // [NArray] return value, grid points of fe along zdim
|
1247
1320
|
VALUE nze; // [NArray] return value, valid data lengths along zdim in fe
|
1248
1321
|
VALUE result; // [Array] [fe, ze, nze] (return the two in an Array)
|
1249
1322
|
struct NARRAY *na;
|
1250
|
-
int rank, zd, d;
|
1323
|
+
int rank, zd, d, w_mis, mis;
|
1251
1324
|
na_shape_t n0, nz, n2, nc;
|
1252
1325
|
double *fv, *zcv, *zbv, *fbv, *fev, *zev;
|
1326
|
+
double ze_filv, rmis;
|
1253
1327
|
int32_t *nzev;
|
1254
1328
|
int zcincr, capupper, sgn;
|
1255
1329
|
na_shape_t j, k, l;
|
@@ -1266,11 +1340,15 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1266
1340
|
zcrd = na_cast_object(zcrd, NA_DFLOAT);
|
1267
1341
|
zb = na_cast_object(zb, NA_DFLOAT);
|
1268
1342
|
if(fb != Qnil){ fb = na_cast_object(fb, NA_DFLOAT); }
|
1343
|
+
w_mis = (misval != Qnil);
|
1344
|
+
if (w_mis) {
|
1345
|
+
rmis = NUM2DBL(misval);
|
1346
|
+
}
|
1269
1347
|
|
1270
1348
|
// read & check
|
1271
1349
|
|
1272
1350
|
rank = NA_RANK(f);
|
1273
|
-
if (NA_RANK(zb)!=rank-1){rb_raise(rb_eArgError,
|
1351
|
+
if (NA_RANK(zb)!=rank-1){rb_raise(rb_eArgError,"zb.rank must be f.rank-1");}
|
1274
1352
|
|
1275
1353
|
zd = NUM2INT(zdim);
|
1276
1354
|
if (zd < 0) zd += rank; // negative: count from the last dim
|
@@ -1316,6 +1394,11 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1316
1394
|
rb_raise(rb_eArgError,"Unexpected data alignment: To ensure that the zdim dimension of the output NArray (fe, ze) starts from the valid data (i.e., its beginning is inside the domain), it should be either that zcrd is increasing and upper==true or that zcrd is decreasing and upper==false");
|
1317
1395
|
}
|
1318
1396
|
|
1397
|
+
if (capupper) {
|
1398
|
+
ze_filv = 1e200;
|
1399
|
+
} else {
|
1400
|
+
ze_filv = -1e200;
|
1401
|
+
}
|
1319
1402
|
// prepare the output array
|
1320
1403
|
|
1321
1404
|
nc = nz+1;
|
@@ -1355,7 +1438,7 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1355
1438
|
}
|
1356
1439
|
for (j=0; j<n0; j++){
|
1357
1440
|
fev[ID3c(j,nc-1,l)] = 0e0; // clear
|
1358
|
-
zev[ID3c(j,nc-1,l)] =
|
1441
|
+
zev[ID3c(j,nc-1,l)] = ze_filv; // clear
|
1359
1442
|
}
|
1360
1443
|
}
|
1361
1444
|
|
@@ -1364,7 +1447,8 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1364
1447
|
for (l=0; l<n2; l++){
|
1365
1448
|
for (j=0; j<n0; j++){
|
1366
1449
|
for (k=0; k<nz; k++){
|
1367
|
-
|
1450
|
+
mis = (w_mis && fv[ID3z(j,k,l)] == rmis);
|
1451
|
+
if ( mis || (zcv[k] - zbv[ID2(j,l)])*sgn > 0 ){
|
1368
1452
|
fev[ID3c(j,k,l)] = fbv[ID2(j,l)];
|
1369
1453
|
zev[ID3c(j,k,l)] = zbv[ID2(j,l)];
|
1370
1454
|
nzev[ID2(j,l)] = k+1;
|
@@ -1383,12 +1467,13 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1383
1467
|
for (l=0; l<n2; l++){
|
1384
1468
|
for (j=0; j<n0; j++){
|
1385
1469
|
for (k=0; k<nz; k++){
|
1386
|
-
|
1387
|
-
|
1388
|
-
fev[ID3c(j,k,l)] =
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1470
|
+
mis = (w_mis && fv[ID3z(j,k,l)] == rmis);
|
1471
|
+
if ( mis || (zcv[k] - zbv[ID2(j,l)])*sgn > 0 ){
|
1472
|
+
fev[ID3c(j,k,l)] = fv[ID3z(j,k-1,l)];//naive extension
|
1473
|
+
//fev[ID3c(j,k,l)] =
|
1474
|
+
// ( fv[ID3z(j,k-1,l)]*(zcv[k]-zbv[ID2(j,l)])
|
1475
|
+
// + fv[ID3z(j,k,l)]*(zbv[ID2(j,l)]-zcv[k-1]) ) /
|
1476
|
+
// (zcv[k] - zcv[k-1]);
|
1392
1477
|
zev[ID3c(j,k,l)] = zbv[ID2(j,l)];
|
1393
1478
|
nzev[ID2(j,l)] = k+1;
|
1394
1479
|
break;
|
@@ -1409,6 +1494,211 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
|
|
1409
1494
|
return result;
|
1410
1495
|
}
|
1411
1496
|
|
1497
|
+
/*
|
1498
|
+
c_val_crossing (C extension): find the positions or the values of y where the values of z crosses zval along dim (using the linear interpolation)
|
1499
|
+
|
1500
|
+
ARGUMENT
|
1501
|
+
* z [NArray of float or sfloat]
|
1502
|
+
* zmask [nil or NArray byte]
|
1503
|
+
* dim [Integer]
|
1504
|
+
* zval [Numeric]
|
1505
|
+
* y [nil or NArray of float or sfloat] if nil, dim indices are used
|
1506
|
+
* nth [Integer] 1,2,3,... for the 1st, 2nd, 3rd,... crossing
|
1507
|
+
* descend [true, false, or nil] true: inspect dim indices from the last
|
1508
|
+
* incr [nil, true, or false] nil: any crsossing is detected; true:
|
1509
|
+
only increasing crossing is detected; false: only decreasing crossing is ..
|
1510
|
+
|
1511
|
+
RETURN VALUE
|
1512
|
+
* yc [NArray double or float] : value of y at the crossing
|
1513
|
+
* ycmask [NArray byte]: mask Array to create NArrayMiss from yc & ycmask
|
1514
|
+
*/
|
1515
|
+
static VALUE
|
1516
|
+
val_crossing(obj, z, zmask, dim, zval, y, nth, descend, incr)
|
1517
|
+
VALUE obj;
|
1518
|
+
VALUE z;
|
1519
|
+
VALUE zmask;
|
1520
|
+
VALUE dim;
|
1521
|
+
VALUE zval;
|
1522
|
+
VALUE y;
|
1523
|
+
VALUE nth;
|
1524
|
+
VALUE descend;
|
1525
|
+
VALUE incr;
|
1526
|
+
{
|
1527
|
+
VALUE yc; // return value 1 (NArray)
|
1528
|
+
VALUE ycmask; // return value 2 (NArray byte)
|
1529
|
+
double *yc_d;
|
1530
|
+
float *yc_f;
|
1531
|
+
u_int8_t *ycmsk;
|
1532
|
+
int rank, dm, d, y1d;
|
1533
|
+
struct NARRAY *na;
|
1534
|
+
na_shape_t *shape, *oshape;
|
1535
|
+
double *z_d, *y_d, zcv, z1, z2;
|
1536
|
+
float *z_f, *y_f;
|
1537
|
+
int zmis;
|
1538
|
+
u_int8_t *zmsk;
|
1539
|
+
na_shape_t n0, n1, n2;
|
1540
|
+
na_shape_t j, k, l;
|
1541
|
+
double a; // fractional position: 0<=a<=1
|
1542
|
+
na_shape_t kf, ke, kstp;
|
1543
|
+
int zdbl, ydbl;
|
1544
|
+
int ith, nthv;
|
1545
|
+
int icross, dcross;
|
1546
|
+
double fillv = 9.9692099683868690e+36; // from NetCDF
|
1547
|
+
|
1548
|
+
if (!IsNArray(z)) {rb_raise(rb_eArgError, "z must be a NArray");}
|
1549
|
+
if (y!= Qnil && !IsNArray(y)) {
|
1550
|
+
rb_raise(rb_eArgError, "y must be nill or a NArray");
|
1551
|
+
}
|
1552
|
+
|
1553
|
+
rank = NA_RANK(z);
|
1554
|
+
GetNArray(z, na);
|
1555
|
+
shape = na->shape;
|
1556
|
+
|
1557
|
+
if ( NA_TYPE(z) == NA_DFLOAT) {
|
1558
|
+
zdbl = 1; // true
|
1559
|
+
z_d = (double *)NA_PTR(na, 0);
|
1560
|
+
} else if (NA_TYPE(z) == NA_SFLOAT) {
|
1561
|
+
zdbl = 0; // false
|
1562
|
+
z_f = (float *)NA_PTR(na, 0);
|
1563
|
+
} else {
|
1564
|
+
rb_raise(rb_eArgError, "z must be a DFLOAT or SFLOAT NArray");
|
1565
|
+
}
|
1566
|
+
|
1567
|
+
if (zmask == Qnil) {
|
1568
|
+
zmis = 0; // no need to consider data missing;
|
1569
|
+
} else {
|
1570
|
+
if (!IsNArray(zmask)) {rb_raise(rb_eArgError, "zmask is not a NArray");}
|
1571
|
+
zmis = 1; // data missing may exist
|
1572
|
+
GetNArray(zmask, na);
|
1573
|
+
zmsk = (u_int8_t *)NA_PTR(na, 0);
|
1574
|
+
}
|
1575
|
+
|
1576
|
+
|
1577
|
+
dm = NUM2INT(dim);
|
1578
|
+
if (dm < 0) dm += rank; // negative: count from the last dim
|
1579
|
+
|
1580
|
+
if (dm < 0 || dm >= rank){
|
1581
|
+
rb_raise(rb_eArgError,
|
1582
|
+
"Invalid dimension (%d) for a rank %d NArray", NUM2INT(dim), rank);
|
1583
|
+
}
|
1584
|
+
|
1585
|
+
zcv = NUM2DBL(zval);
|
1586
|
+
|
1587
|
+
oshape = ALLOCA_N(na_shape_t, rank-1);
|
1588
|
+
for (d=0, n0=1 ; d<dm ; d++){
|
1589
|
+
n0 *= shape[d];
|
1590
|
+
oshape[d] = shape[d];
|
1591
|
+
}
|
1592
|
+
n1 = shape[dm];
|
1593
|
+
for (d=dm+1, n2=1 ; d<rank ; d++){
|
1594
|
+
n2 *= shape[d];
|
1595
|
+
oshape[d-1] = shape[d];
|
1596
|
+
}
|
1597
|
+
|
1598
|
+
if ( descend == Qtrue ){
|
1599
|
+
kf = n1-1;
|
1600
|
+
ke = -1;
|
1601
|
+
kstp = -1;
|
1602
|
+
} else {
|
1603
|
+
kf = 0;
|
1604
|
+
ke = n1;
|
1605
|
+
kstp = 1;
|
1606
|
+
}
|
1607
|
+
|
1608
|
+
if ( incr == Qnil ){
|
1609
|
+
icross = 1;
|
1610
|
+
dcross = 1;
|
1611
|
+
} else if ( incr == Qtrue ){
|
1612
|
+
icross = 1;
|
1613
|
+
dcross = 0;
|
1614
|
+
} else {
|
1615
|
+
icross = 0;
|
1616
|
+
dcross = 1;
|
1617
|
+
}
|
1618
|
+
|
1619
|
+
nthv = NUM2INT(nth);
|
1620
|
+
if (nthv <= 0) {
|
1621
|
+
rb_raise(rb_eArgError, "nth (%d) must be positive (1,2,...)", nthv);
|
1622
|
+
}
|
1623
|
+
|
1624
|
+
if ( y == Qnil ) {
|
1625
|
+
ydbl = 1; // true
|
1626
|
+
y1d = 1; // true
|
1627
|
+
y_d = ALLOCA_N(double, n1);
|
1628
|
+
for (k=0; k<n1; k++) {y_d[k] = (double) k;}
|
1629
|
+
} else {
|
1630
|
+
GetNArray(y, na);
|
1631
|
+
if ( NA_TYPE(y) == NA_DFLOAT) {
|
1632
|
+
ydbl = 1; // true
|
1633
|
+
y_d = (double *)NA_PTR(na, 0);
|
1634
|
+
} else if (NA_TYPE(y) == NA_SFLOAT) {
|
1635
|
+
ydbl = 0; // false
|
1636
|
+
y_f = (float *)NA_PTR(na, 0);
|
1637
|
+
} else {
|
1638
|
+
rb_raise(rb_eArgError, "expects a DFLOAT or SFLOAT NArray");
|
1639
|
+
}
|
1640
|
+
if (NA_TOTAL(y) == n1) {
|
1641
|
+
// treated as 1D along dim
|
1642
|
+
y1d = 1; // true
|
1643
|
+
} else if (NA_TOTAL(y) == NA_TOTAL(z)) {
|
1644
|
+
// treated as y and z share a shape
|
1645
|
+
y1d = 0; // false
|
1646
|
+
} else {
|
1647
|
+
rb_raise(rb_eArgError, "Shape (length) of y mismatches that of z");
|
1648
|
+
}
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
if (ydbl) {
|
1652
|
+
yc = na_make_object(NA_DFLOAT, rank-1, oshape, cNArray);
|
1653
|
+
yc_d = NA_PTR_TYPE(yc, double *);
|
1654
|
+
for (j=0; j<n0*n2; j++){yc_d[j] = fillv;}
|
1655
|
+
} else {
|
1656
|
+
yc = na_make_object(NA_SFLOAT, rank-1, oshape, cNArray);
|
1657
|
+
yc_f = NA_PTR_TYPE(yc, float *);
|
1658
|
+
for (j=0; j<n0*n2; j++){yc_f[j] = (float) fillv;}
|
1659
|
+
}
|
1660
|
+
ycmask = na_make_object(NA_BYTE, rank-1, oshape, cNArray);
|
1661
|
+
ycmsk = NA_PTR_TYPE(ycmask, u_int8_t *);
|
1662
|
+
for (j=0; j<n0*n2; j++){ycmsk[j] = 0;}
|
1663
|
+
|
1664
|
+
for (l=0; l<n2; l++){
|
1665
|
+
for (j=0; j<n0; j++){
|
1666
|
+
z1 = ( zdbl ? z_d[ID3(j,kf,l)] : z_f[ID3(j,kf,l)] );
|
1667
|
+
ith = 0;
|
1668
|
+
for (k=kf+kstp; k!=ke; k+=kstp) {
|
1669
|
+
z2 = ( zdbl ? z_d[ID3(j,k,l)] : z_f[ID3(j,k,l)] );
|
1670
|
+
if ( ( !zmis || (zmsk[ID3(j,k-kstp,l)] && zmsk[ID3(j,k,l)]) ) &&
|
1671
|
+
( icross && z1<zcv && zcv<=z2 ||
|
1672
|
+
dcross && z1>zcv && zcv>=z2 ) ){
|
1673
|
+
ith++;
|
1674
|
+
if (ith == nthv){
|
1675
|
+
a = (zcv-z1) / (z2-z1);
|
1676
|
+
if (y1d) {
|
1677
|
+
if (ydbl) {
|
1678
|
+
yc_d[ID2(j,l)] = (1.0-a)*y_d[k-kstp] + a*y_d[k];
|
1679
|
+
} else {
|
1680
|
+
yc_f[ID2(j,l)] = (1.0-a)*y_f[k-kstp] + a*y_f[k];
|
1681
|
+
}
|
1682
|
+
} else {
|
1683
|
+
if (ydbl) {
|
1684
|
+
yc_d[ID2(j,l)] = (1.0-a)*y_d[ID3(j,k-kstp,l)]
|
1685
|
+
+ a*y_d[ID3(j,k,l)];
|
1686
|
+
} else {
|
1687
|
+
yc_f[ID2(j,l)] = (1.0-a)*y_f[ID3(j,k-kstp,l)]
|
1688
|
+
+ a*y_f[ID3(j,k,l)];
|
1689
|
+
}
|
1690
|
+
}
|
1691
|
+
ycmsk[ID2(j,l)] = 1;
|
1692
|
+
break;
|
1693
|
+
}
|
1694
|
+
}
|
1695
|
+
z1 = z2;
|
1696
|
+
}
|
1697
|
+
}
|
1698
|
+
}
|
1699
|
+
return rb_ary_new3(2, yc, ycmask);
|
1700
|
+
}
|
1701
|
+
|
1412
1702
|
void
|
1413
1703
|
init_gphys_dim_op()
|
1414
1704
|
{
|
@@ -1432,9 +1722,11 @@ init_gphys_dim_op()
|
|
1432
1722
|
rb_define_singleton_method(cGPhys, "c_bin_sum", bin_sum, -1);
|
1433
1723
|
|
1434
1724
|
rb_define_private_method(cVArray, "c_cum_sum", cum_sum, 2);
|
1725
|
+
rb_define_singleton_method(cGPhys, "c_cum_sum", cum_sum, 2);
|
1435
1726
|
rb_define_singleton_method(cGPhys, "c_cell_integ_irreg",
|
1436
|
-
cell_integ_irreg,
|
1437
|
-
rb_define_singleton_method(cGPhys, "c_cum_integ_irreg", cum_integ_irreg,
|
1727
|
+
cell_integ_irreg, 7);
|
1728
|
+
rb_define_singleton_method(cGPhys, "c_cum_integ_irreg", cum_integ_irreg, 7);
|
1438
1729
|
|
1439
|
-
rb_define_singleton_method(cGPhys, "c_cap_by_boundary", cap_by_boundary,
|
1730
|
+
rb_define_singleton_method(cGPhys, "c_cap_by_boundary", cap_by_boundary, 7);
|
1731
|
+
rb_define_singleton_method(cGPhys, "c_val_crossing", val_crossing, 8);
|
1440
1732
|
}
|