29 #define HPI (0.5*M_PI) 30 #define TPI (2.0*M_PI) 31 #define TOLORENCE (1.e-6) 32 #define EPSLN8 (1.e-8) 33 #define EPSLN10 (1.e-10) 34 #define EPSLN15 (1.e-15) 35 #define EPSLN30 (1.e-30) 57 fprintf(stderr,
"FATAL Error: %s\n", msg );
59 MPI_Abort(MPI_COMM_WORLD, -1);
86 if (array[
i] < array[
i-1])
87 error_handler(
"nearest_index: array must be monotonically increasing");
89 if (value < array[0] )
91 else if ( value > array[ia-1])
97 while (
i < ia && keep_going) {
99 if (value <= array[
i]) {
101 if (array[
i]-value > value-array[
i-1]) index =
i-1;
112 void tokenize(
const char *
const string,
const char *tokens,
unsigned int varlen,
113 unsigned int maxvar,
char * pstring,
unsigned int *
const nstr)
122 if(
string[0] == 0)
error_handler(
"Error from tokenize: to-be-parsed string is empty");
124 for(
i = 0;
i <
len;
i ++){
125 if(
string[
i] !=
' ' &&
string[
i] !=
'\t'){
127 for(
n=0;
n<ntoken;
n++) {
128 if(
string[
i] == tokens[
n] ) {
135 *(pstring + (
nvar++)*varlen +
j) = 0;
137 if(
nvar >= maxvar)
error_handler(
"Error from tokenize: number of variables exceeds limit");
141 *(pstring +
nvar*varlen +
j++) =
string[
i];
142 if(
j >= varlen )
error_handler(
"error from tokenize: variable name length exceeds limit during tokenization");
146 *(pstring +
nvar*varlen +
j) = 0;
163 if( data[
n] > maxval ) maxval = data[
n];
182 if( data[
n] < minval ) minval = data[
n];
199 for(
n=0;
n<
size;
n++) avgval += data[
n];
227 void xyz2latlon(
int np,
const double *x,
const double *y,
const double *z,
double *
lon,
double *
lat)
234 for(
i=0;
i<np;
i++) {
238 dist = sqrt(xx*xx+yy*yy+zz*zz);
243 if ( fabs(xx)+fabs(yy) <
EPSLN10 )
246 lon[
i] = atan2(yy, xx);
258 double box_area(
double ll_lon,
double ll_lat,
double ur_lon,
double ur_lat)
260 double dx = ur_lon-ll_lon;
262 if(dx > M_PI) dx = dx - 2.0*M_PI;
263 if(dx < -M_PI) dx = dx + 2.0*M_PI;
284 double dx = (x[
ip]-x[
i]);
290 if(dx > M_PI) dx = dx - 2.0*M_PI;
291 if(dx < -M_PI) dx = dx + 2.0*M_PI;
292 if (dx==0.0)
continue;
301 dy = 0.5*(lat1-
lat2);
303 area -= dx*sin(0.5*(lat1+
lat2))*dat;
308 return (-
area/(4*M_PI));
310 return (
area/(4*M_PI));
321 double dx = (x[
ip]-x[
i]);
327 if(dx > M_PI) dx = dx - 2.0*M_PI;
328 if(dx < -M_PI) dx = dx + 2.0*M_PI;
329 if (dx==0.0)
continue;
338 dy = 0.5*(lat1-
lat2);
340 area -= dx*sin(0.5*(lat1+
lat2))*dat;
358 double dx = (x[
ip]-x[
i]);
363 if (dx==0.0)
continue;
378 for (;n_del<
n-1;n_del++) {
379 x[n_del] = x[n_del+1];
380 y[n_del] = y[n_del+1];
386 int insert_vtx(
double x[],
double y[],
int n,
int n_ins,
double lon_in,
double lat_in)
390 for (
i=
n-1;
i>=n_ins;
i--) {
405 printf(
" %20g %20g\n", x[
i], y[
i]);
409 int fix_lon(
double x[],
double y[],
int n,
double tlon)
411 double x_sum, dx, dx_;
412 int i, nn =
n, pole = 0;
416 printf(
"fixing pole cell\n");
423 int im=(
i+nn-1)%nn,
ip=(
i+1)%nn;
425 if (y[
im]==y[
i] && y[
ip]==y[
i]) {
428 }
else if (y[
im]!=y[
i] && y[
ip]!=y[
i]) {
436 int im=(
i+nn-1)%nn,
ip=(
i+1)%nn;
455 if (dx_ < -M_PI) dx_ = dx_ +
TPI;
456 else if (dx_ > M_PI) dx_ = dx_ -
TPI;
457 x_sum += (x[
i] = x[
i-1] + dx_);
460 dx = (x_sum/nn)-tlon;
495 beta = 2.*asin( sqrt( sin((
p1[1]-
p2[1])/2.)*sin((
p1[1]-
p2[1])/2.) +
496 cos(
p1[1])*cos(
p2[1])*(sin((
p1[0]-
p2[0])/2.)*sin((
p1[0]-
p2[0])/2.)) ) );
506 double pnt0[3], pnt1[3], pnt2[3];
511 for (
i=0;
i<
n;
i++) {
516 pnt1[0] = x[(
i+1)%
n];
517 pnt1[1] = y[(
i+1)%
n];
518 pnt1[2] = z[(
i+1)%
n];
519 pnt2[0] = x[(
i+2)%
n];
520 pnt2[1] = y[(
i+2)%
n];
521 pnt2[2] = z[(
i+2)%
n];
544 #ifdef NO_QUAD_PRECISION 545 double px, py, pz, qx, qy, qz, ddd;
549 #error "SQRT_ Previously Defined" 554 #error "ABS_ Previously Defined" 557 long double px, py, pz, qx, qy, qz, ddd;
561 #error "SQRT_ Previously Defined" 566 #error "ABS_ Previously Defined" 571 px = v1[1]*v2[2] - v1[2]*v2[1];
572 py = v1[2]*v2[0] - v1[0]*v2[2];
573 pz = v1[0]*v2[1] - v1[1]*v2[0];
575 qx = v1[1]*v3[2] - v1[2]*v3[1];
576 qy = v1[2]*v3[0] - v1[0]*v3[2];
577 qz = v1[0]*v3[1] - v1[1]*v3[0];
579 ddd = (px*px+py*py+pz*pz)*(qx*qx+qy*qy+qz*qz);
583 ddd = (px*qx+py*qy+pz*qz) /
SQRT_(ddd);
586 if ( ddd>1. || ddd<-1. ) {
607 const double* p_lr,
const double* p_ur,
double radius)
609 double area, ang1, ang2, ang3, ang4;
610 double v1[3], v2[3], v3[3];
663 double dot(
const double *
p1,
const double *
p2)
672 return (sqrt(
p[0]*
p[0] +
p[1]*
p[1]+
p[2]*
p[2]) );
684 pdot =
e[0]*
e[0] +
e[1] *
e[1] +
e[2] *
e[2];
687 for(
k=0;
k<3;
k++)
e[
k] /= pdot;
699 double sin_lon, cos_lon, sin_lat, cos_lat;
703 sin_lon = sin(
lon[
n]);
704 cos_lon = cos(
lon[
n]);
705 sin_lat = sin(
lat[
n]);
706 cos_lat = cos(
lat[
n]);
708 vlon[3*
n] = -sin_lon;
709 vlon[3*
n+1] = cos_lon;
712 vlat[3*
n] = -sin_lat*cos_lon;
713 vlat[3*
n+1] = -sin_lat*sin_lon;
714 vlat[3*
n+2] = cos_lat;
730 long double M[3*3], inv_M[3*3];
735 const double *pnt0=plane;
736 const double *pnt1=plane+3;
737 const double *pnt2=plane+6;
742 M[0]=l1[0]-l2[0]; M[1]=pnt1[0]-pnt0[0]; M[2]=pnt2[0]-pnt0[0];
743 M[3]=l1[1]-l2[1]; M[4]=pnt1[1]-pnt0[1]; M[5]=pnt2[1]-pnt0[1];
744 M[6]=l1[2]-l2[2]; M[7]=pnt1[2]-pnt0[2]; M[8]=pnt2[2]-pnt0[2];
749 if (!is_invert)
return 0;
768 void mult(
long double m[],
long double v[],
long double out_v[]) {
770 out_v[0]=
m[0]*
v[0]+
m[1]*
v[1]+
m[2]*
v[2];
771 out_v[1]=
m[3]*
v[0]+
m[4]*
v[1]+
m[5]*
v[2];
772 out_v[2]=
m[6]*
v[0]+
m[7]*
v[1]+
m[8]*
v[2];
781 const long double det =
m[0] * (
m[4]*
m[8] -
m[5]*
m[7])
782 -
m[1] * (
m[3]*
m[8] -
m[5]*
m[6])
783 +
m[2] * (
m[3]*
m[7] -
m[4]*
m[6]);
784 #ifdef test_invert_matrix_3x3 785 printf(
"det = %Lf\n",
det);
789 const long double deti = 1.0/
det;
791 m_inv[0] = (
m[4]*
m[8] -
m[5]*
m[7]) * deti;
792 m_inv[1] = (
m[2]*
m[7] -
m[1]*
m[8]) * deti;
793 m_inv[2] = (
m[1]*
m[5] -
m[2]*
m[4]) * deti;
795 m_inv[3] = (
m[5]*
m[6] -
m[3]*
m[8]) * deti;
796 m_inv[4] = (
m[0]*
m[8] -
m[2]*
m[6]) * deti;
797 m_inv[5] = (
m[2]*
m[3] -
m[0]*
m[5]) * deti;
799 m_inv[6] = (
m[3]*
m[7] -
m[4]*
m[6]) * deti;
800 m_inv[7] = (
m[1]*
m[6] -
m[0]*
m[7]) * deti;
801 m_inv[8] = (
m[0]*
m[4] -
m[1]*
m[3]) * deti;
807 #define MAXNODELIST 100 895 int is1,
int ie1,
int is2,
int ie2)
898 double u1_cur, u2_cur;
921 if( temp->
u == u1_cur && temp->
subj_index == i1_cur)
return 0;
923 if( !temp->
Next )
break;
961 cur_ptr=cur_ptr->
Next;
968 int samePoint(
double x1,
double y1,
double z1,
double x2,
double y2,
double z2)
980 if( node1.
x == node2.
x && node1.
y == node2.
y && node1.
z==node2.
z )
1020 node_out->
x = node_in.
x;
1021 node_out->
y = node_in.
y;
1022 node_out->
z = node_in.
z;
1023 node_out->
u = node_in.
u;
1036 if(
str) printf(
" %s \n",
str);
1040 printf(
" (x, y, z, interset, inbound, isInside) = (%19.15f,%19.15f,%19.15f,%d,%d,%d)\n",
1055 if( temp->
x ==
x && temp->
y ==
y && temp->
z ==
z ) {
1061 if (!found)
error_handler(
"intersectInList: point (x,y,z) is not found in the list");
1075 double x2,
double y2,
double z2)
1091 if (!found)
error_handler(
"inserAfter: point (x,y,z) is not found in the list");
1101 temp1->intersect = 2;
1102 temp1->isInside = 1;
1111 if(
u2 != 0 &&
u2 != 1) {
1116 while(
temp2->intersect) {
1121 temp2->isInside = 0;
1124 temp1->isInside = 0;
1130 if(
temp2->intersect == 1 ) {
1131 if(
temp2->u > u_cur ) {
1157 double x[20],
y[20],
z[20];
1196 while(
temp1->Next ) {
1261 int prev_is_inside, next_is_inside;
1265 if(
length(interList) == 0)
return;
1270 if( !temp->inbound) {
1278 if(!temp1_prev) temp1_prev =
getLast(list);
1279 temp1_next =
temp1->Next;
1280 if(!temp1_next) temp1_next = list;
1286 if(!temp1_next)
error_handler(
"Error from create_xgrid.c: temp is not in list1");
1287 if( temp1_prev->
isInside == 0 && temp1_next->isInside == 1)
1309 double pnt0[3], pnt1[3], pnt2[3];
1331 if(
samePoint(pnt0[0], pnt0[1], pnt0[2], pnt1[0], pnt1[1], pnt1[2]) ){
1342 if( fabs(anglesum - 2*M_PI) <
EPSLN8 ){
1349 #ifdef debug_test_create_xgrid 1350 printf(
"anglesum-2PI is %19.15f, is_inside = %d\n", anglesum- 2*M_PI, is_inside);
1360 double x2[20], y2[20], z2[20];
1362 double min_x2, max_x2, min_y2, max_y2, min_z2, max_z2;
1392 addEnd(grid1, x1, y1, z1, 0, 0, 0, -1);
int getFirstInbound(struct Node *list, struct Node *nodeOut)
real, parameter, public radius
Radius of the Earth [m].
l_size ! loop over number of fields ke do je do i
void error_handler(const char *msg)
integer, parameter, public strlen
double gridArea(struct Node *grid)
real function intersect(x1, y1, x2, y2, x)
double metric(const double *p)
void setInbound(struct Node *interList, struct Node *list)
real(fvprc), dimension(:), allocatable lon
#define RANGE_CHECK_CRITERIA
integer, parameter, public ip
int nearest_index(double value, const double *array, int ia)
struct Node * getLast(struct Node *list)
int intersect_tri_with_line(const double *plane, const double *l1, const double *l2, double *p, double *t)
void tokenize(const char *const string, const char *tokens, unsigned int varlen, unsigned int maxvar, char *pstring, unsigned int *const nstr)
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************! this routine is used to retrieve scalar boundary data for symmetric domain. subroutine MPP_GET_BOUNDARY_2D_(field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &position, complete, tile_count) type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::field(:,:) MPP_TYPE_, intent(inout), optional ::ebuffer(:), sbuffer(:), wbuffer(:), nbuffer(:) integer, intent(in), optional ::flags, position, tile_count logical, intent(in), optional ::complete MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_, allocatable, dimension(:,:) ::ebuffer2D, sbuffer2D, wbuffer2D, nbuffer2D integer ::xcount, ycount integer ::ntile logical ::need_ebuffer, need_sbuffer, need_wbuffer, need_nbuffer integer(LONG_KIND), dimension(MAX_DOMAIN_FIELDS, MAX_TILES), save ::f_addrs=-9999 integer(LONG_KIND), dimension(4, MAX_DOMAIN_FIELDS, MAX_TILES), save ::b_addrs=-9999 integer, save ::bsize(4)=0, isize=0, jsize=0, ksize=0, pos, list=0, l_size=0, upflags integer ::buffer_size(4) integer ::max_ntile, tile, update_position, ishift, jshift logical ::do_update, is_complete, set_mismatch character(len=3) ::text MPP_TYPE_ ::d_type type(overlapSpec), pointer ::bound=> NULL() ntile
void vect_cross(const double *p1, const double *p2, double *e)
real, dimension(:,:), allocatable temp1
integer, parameter, public double
void addEnd(struct Node *list, double x, double y, double z, int intersect, double u, int inbound, int inside)
void xyz2latlon(int np, const double *x, const double *y, const double *z, double *lon, double *lat)
double spherical_angle(const double *v1, const double *v2, const double *v3)
void copyNode(struct Node *node_out, struct Node node_in)
int inside_a_polygon_(double *lon1, double *lat1, int *npts, double *lon2, double *lat2)
real(r8), dimension(cast_m, cast_n) p
l_size ! loop over number of fields ke do j
double spherical_excess_area(const double *p_ll, const double *p_ul, const double *p_lr, const double *p_ur, double radius)
struct Node * getNextNode(struct Node *list)
void set_reproduce_siena_true_(void)
int insidePolygon(struct Node *node, struct Node *list)
double great_circle_area(int n, const double *x, const double *y, const double *z)
double avgval_double(int size, const double *data)
struct Node * getNode(struct Node *list, struct Node inNode)
real(fp), parameter, public e
integer nvar
No description.
int insert_vtx(double x[], double y[], int n, int n_ins, double lon_in, double lat_in)
real, dimension(:,:), allocatable area
real(kind=kind_real), parameter u1
double great_circle_distance(double *p1, double *p2)
double poly_area_dimensionless(const double x[], const double y[], int n)
real, dimension(:,:), allocatable temp2
void v_print(double x[], double y[], int n)
double box_area(double ll_lon, double ll_lat, double ur_lon, double ur_lat)
real(fvprc), dimension(:), allocatable lat
int isIntersect(struct Node node)
int sameNode(struct Node node1, struct Node node2)
void insertIntersect(struct Node *list, double x, double y, double z, double u1, double u2, int inbound, double x2, double y2, double z2)
void addNode(struct Node *list, struct Node inNode)
int length(struct Node *list)
integer, parameter, public npts
int samePoint(double x1, double y1, double z1, double x2, double y2, double z2)
int inside_a_polygon(double *lon1, double *lat1, int *npts, double *lon2, double *lat2)
void normalize_vect(double *e)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
int fix_lon(double x[], double y[], int n, double tlon)
int intersectInList(struct Node *list, double x, double y, double z)
void set_reproduce_siena_true(void)
real(r8), dimension(cast_m, cast_n) t
double poly_area(const double x[], const double y[], int n)
void getCoordinate(struct Node node, double *x, double *y, double *z)
double minval_double(int size, const double *data)
void setCoordinate(struct Node *node, double x, double y, double z)
double dot(const double *p1, const double *p2)
int getInbound(struct Node node)
real function, private angle(t)
angle determines the position within the earth's orbit at time t in the year (t = 0 at NH autumnal eq...
void latlon2xyz(int size, const double *lon, const double *lat, double *x, double *y, double *z)
int isInside(struct Node *node)
void mult(long double m[], long double v[], long double out_v[])
int invert_matrix_3x3(long double m[], long double m_inv[])
double maxval_double(int size, const double *data)
int addIntersect(struct Node *list, double x, double y, double z, int intersect, double u1, double u2, int inbound, int is1, int ie1, int is2, int ie2)
double poly_area_no_adjust(const double x[], const double y[], int n)
void initNode(struct Node *node)
int delete_vtx(double x[], double y[], int n, int n_del)
real(kind=kind_real), parameter u2
void getCoordinates(struct Node *node, double *p)
void printNode(struct Node *list, char *str)
void unit_vect_latlon(int size, const double *lon, const double *lat, double *vlon, double *vlat)