def arc12_pt3(xyz1, xyz2, xyz3): ''' Three points should be on same circle. ''' vec1 = x1, y1, z1 = xyz1 vec2 = x2, y2, z2 = xyz2 vec3 = x3, y3, z3 = xyz3 unit_nvec = normal_vector(vec1, vec2, normalize=True) cp1 = np.dot(unit_nvec, np.cross(vec1, vec3)) cp2 = np.dot(unit_nvec, np.cross(vec2, vec3)) if feq(cp1,0): if feq(cp2,0): raise ValueError("cp1 and cp2 are both zero") elif flt(cp2,0): return 'pt1' elif fgt(cp2,0): return 'out' elif flt(cp1,0): return 'out' elif fgt(cp1,0): if feq(cp2,0): return 'pt2' elif flt(cp2,0): return 'between' elif fgt(cp2,0): return 'out'
def xyz2latlon(x, y, z, R=1): ''' if feq(z,R): lat, lon = pi/2, 0 elif feq(z,-R): lat, lon = -pi/2, 0 ''' if feq(sqrt(x*x + y*y),0): if z > 0: lat, lon = pi/2, 0 elif z < 0: lat, lon = -pi/2, 0 else: lat = arctan(z/sqrt(x*x + y*y)) if feq(x,0): if fgt(y,0): lon = pi/2 else: lon = 3*pi/2 elif fgt(x,0): if fgt(y,0): lon = arctan(y/x) else: lon = arctan(y/x) + 2*pi else: lon = arctan(y/x) + pi return lat, lon
def duplicate_idxs(xyzs, digit=15): size = len(xyzs) dup_idxs = list() for i in range(size): for j in range(i+1,size): x1, y1, z1 = xyzs[i] x2, y2, z2 = xyzs[j] if feq(x1,x2,digit) and feq(y1,y2,digit) and feq(z1,z2,digit): dup_idxs.append(j) return dup_idxs
def intersect_two_greatcircles(abc1, abc2): ''' Two intersection points of two planes and a sphere Input are plane parameters. ''' a1, b1, c1 = abc1 a2, b2, c2 = abc2 if feq(a1,a2) and feq(b1,b2) and feq(c1,c2): return None, None elif feq(a1,0) and feq(a2,0): s1, s2 = [(1,0,0), (-1,0,0)] elif feq(b1,0) and feq(b2,0): s1, s2 = [(0,1,0), (0,-1,0)] elif feq(c1,0) and feq(c2,0): s1, s2 = [(0,0,1), (0,0,-1)] elif feq(c2*b1, c1*b2): A = a2*c1-a1*c2 B = a2*b1-a1*b2 denom = A*A + B*B #if feq(denom,0): if denom == 0: return None, None else: Z = 1/np.sqrt(denom) s1 = (0, A*Z, -B*Z) s2 = (0, -A*Z, B*Z) else: A = b2*c1-b1*c2 B = c2*a1-c1*a2 C = b2*a1-b1*a2 denom = A*A + B*B + C*C #if feq(denom,0): if denom == 0: return None, None else: Z = 1/np.sqrt(denom) s1 = (A*Z, B*Z, -C*Z) s2 = (-A*Z, -B*Z, C*Z) return s1, s2
def get_xyz3(self): angle = self.max_angle x1, y1, z1 = self.xyz1 x2, y2, z2 = self.xyz2 c_angle, s_angle = np.cos(angle), np.sin(angle) if feq(s_angle,0): x3, y3, z3 = x2, y2, z2 else: x3 = (x2 - x1*c_angle)/s_angle y3 = (y2 - y1*c_angle)/s_angle z3 = (z2 - z1*c_angle)/s_angle return (x3,y3,z3)
def test_avg_sequential_3_4_1(): ''' CubeMPI for AVG: Exact squential values (ne=3, ngq=4, nproc=1) ''' ne, ngq = 3, 4 nproc, myrank = 1, 0 cubegrid = CubeGridMPI(ne, ngq, nproc, myrank, cs_grid_dpath) cubempi = CubeMPI(cubegrid, 'AVG', spmat_dpath) a_equal(cubegrid.local_gids, np.arange(6*ne*ne*ngq*ngq)) a_equal(cubempi.recv_schedule.shape, (0,3)) a_equal(cubempi.send_schedule.shape, (0,3)) a_equal(cubempi.recv_buf_size, 6*ne*ne*12) a_equal(cubempi.send_buf_size, 0) #----------------------------------------------------- # Generate a sequential field on the cubed-sphere #----------------------------------------------------- f = np.arange(cubegrid.local_ep_size, dtype='f8') #----------------------------------------------------- # Average the element boundary for the spectral element method #----------------------------------------------------- recv_buf = np.zeros(cubempi.recv_buf_size, 'f8') send_buf = np.zeros(cubempi.send_buf_size, 'f8') pre_send(cubempi, f, recv_buf, send_buf) post_recv(cubempi, f, recv_buf) #----------------------------------------------------- # Check if mvps have same values #----------------------------------------------------- fs = [f] ranks, lids = cubegrid.ranks, cubegrid.lids cs_fpath = os.path.join(cs_grid_dpath, "cs_grid_ne{:03d}np{}.nc".format(ne, ngq)) cs_ncf = nc.Dataset(cs_fpath, 'r', format='NETCDF4') mvps = cs_ncf.variables['mvps'][:] for seq, mvp in enumerate(mvps): eff_mvp = [k for k in mvp if k != -1] for gid in eff_mvp: rank, lid = ranks[gid], lids[gid] ok_( feq(fs[rank][lid], np.mean(eff_mvp), 15) )
def plane12_pt3(xyz1, xyz2, xyz3): ''' plane generated by xyz1 and xyz2 left if xyz3 is in normal vector direction ''' plane = plane_origin(xyz1, xyz2) #nvec = normal_vector(xyz1, xyz2) #print np.dot(plane,nvec) # > 0 val = np.dot(plane, xyz3) if feq(val,0): return 'straight' elif flt(val,0): return 'right' elif fgt(val,0): return 'left'
def xyz2xyp(X, Y, Z, R=1): assert feq(sqrt(X*X + Y*Y + Z*Z),R), 'The (x,y,z) (%s,%s,%s) is not on the sphere.'%(X,Y,Z) a = R/sqrt(3) at1, at2 = a*tan(-pi/4), a*tan(pi/4) xyp_dict = dict() if fgt(X,0): x, y = a*(Y/X), a*(Z/X) if flge(at1,x,at2) and flge(at1,y,at2): xyp_dict[1] = (x,y) elif flt(X,0): x, y = a*(Y/X), -a*(Z/X) if flge(at1,x,at2) and flge(at1,y,at2): xyp_dict[3] = (x,y) if fgt(Y,0): x, y = -a*(X/Y), a*(Z/Y) if flge(at1,x,at2) and flge(at1,y,at2): xyp_dict[2] = (x,y) elif flt(Y,0): x, y = -a*(X/Y), -a*(Z/Y) if flge(at1,x,at2) and flge(at1,y,at2): xyp_dict[4] = (x,y) if flt(Z,0): x, y = -a*(Y/Z), -a*(X/Z) if flge(at1,x,at2) and flge(at1,y,at2): xyp_dict[5] = (x,y) elif fgt(Z,0): x, y = a*(Y/Z), -a*(X/Z) if flge(at1,x,at2) and flge(at1,y,at2): xyp_dict[6] = (x,y) return xyp_dict
def check_avg_sequential_mpi(ne, ngq, comm): ''' CubeMPI for AVG ''' myrank = comm.Get_rank() nproc = comm.Get_size() cubegrid = CubeGridMPI(ne, ngq, nproc, myrank, cs_grid_dpath) cubempi = CubeMPI(cubegrid, 'AVG', spmat_dpath, comm=None) # Generate a sequential field on the cubed-sphere f = cubegrid.local_gids.astype('f8') # Average the element boundary for the spectral element method send_buf = np.zeros(cubempi.send_buf_size, 'f8') recv_buf = np.zeros(cubempi.recv_buf_size, 'f8') # Send/Recv pre_send(cubempi, f, recv_buf, send_buf) req_send_list = list() req_recv_list = list() for dest, start, size in cubempi.send_schedule: req = comm.Isend(send_buf[start:start+size], dest, 0) req_send_list.append(req) for dest, start, size in cubempi.recv_schedule: req = comm.Irecv(recv_buf[start:start+size], dest, 0) req_recv_list.append(req) MPI.Request.Waitall(req_send_list) MPI.Request.Waitall(req_recv_list) # After receive post_recv(cubempi, f, recv_buf) #----------------------------------------------------- # Check if mvps have same values #----------------------------------------------------- if myrank == 0: fs = [f] for src in range(1,nproc): size = cubegrid.local_ep_size fs.append( np.zeros(size, 'f8') ) comm.Recv(fs[-1], src, 10) cs_fpath = cs_grid_dpath + "cs_grid_ne{:03d}np{}.nc".format(ne, ngq) cs_ncf = nc.Dataset(cs_fpath, 'r', format='NETCDF4') mvps = cs_ncf.variables['mvps'][:] ranks, lids = cubegrid.ranks, cubegrid.lids for seq, mvp in enumerate(mvps): eff_mvp = [k for k in mvp if k != -1] for gid in eff_mvp: rank, lid = ranks[gid], lids[gid] ok_( feq(fs[rank][lid], np.mean(eff_mvp), 15) ) else: comm.Send(f, 0, 10)
def test_avg_sequential_3_4_3(): ''' CubeMPI for AVG: Exact squential values (ne=3, ngq=4, nproc=3) ''' ne, ngq = 3, 4 nproc = 3 cubegrid0 = CubeGridMPI(ne, ngq, nproc, 0, cs_grid_dpath) cubempi0 = CubeMPI(cubegrid0, 'AVG', spmat_dpath) cubegrid1 = CubeGridMPI(ne, ngq, nproc, 1, cs_grid_dpath) cubempi1 = CubeMPI(cubegrid1, 'AVG', spmat_dpath) cubegrid2 = CubeGridMPI(ne, ngq, nproc, 2, cs_grid_dpath) cubempi2 = CubeMPI(cubegrid2, 'AVG', spmat_dpath) # Check send/recv pair in send_group and recv_group a_equal(list(cubempi0.send_group[1].keys()), cubempi1.recv_group[0]) a_equal(list(cubempi0.send_group[2].keys()), cubempi2.recv_group[0]) a_equal(list(cubempi1.send_group[0].keys()), cubempi0.recv_group[1]) a_equal(list(cubempi1.send_group[2].keys()), cubempi2.recv_group[1]) a_equal(list(cubempi2.send_group[0].keys()), cubempi0.recv_group[2]) a_equal(list(cubempi2.send_group[1].keys()), cubempi1.recv_group[2]) # Check send/recv pair in send_buf and recv_buf rank0, i0, n0 = cubempi0.send_schedule[0] # send 0->1 rank1, i1, n1 = cubempi1.recv_schedule[0] # recv a_equal(cubempi0.send_buf[i0:i0+n0], cubempi1.recv_buf[i1:i1+n1]) rank0, i0, n0 = cubempi1.send_schedule[0] # send 1->0 rank1, i1, n1 = cubempi0.recv_schedule[0] # recv a_equal(cubempi1.send_buf[i0:i0+n0], cubempi0.recv_buf[i1:i1+n1]) rank0, i0, n0 = cubempi0.send_schedule[1] # send 0->2 rank1, i1, n1 = cubempi2.recv_schedule[0] # recv a_equal(cubempi0.send_buf[i0:i0+n0], cubempi2.recv_buf[i1:i1+n1]) rank0, i0, n0 = cubempi2.send_schedule[0] # send 2->0 rank1, i1, n1 = cubempi0.recv_schedule[1] # recv a_equal(cubempi2.send_buf[i0:i0+n0], cubempi0.recv_buf[i1:i1+n1]) rank0, i0, n0 = cubempi1.recv_schedule[1] # send 1->2 rank1, i1, n1 = cubempi2.send_schedule[1] # recv a_equal(cubempi1.recv_buf[i0:i0+n0], cubempi2.send_buf[i1:i1+n1]) rank0, i0, n0 = cubempi2.recv_schedule[1] # send 2->1 rank1, i1, n1 = cubempi1.send_schedule[1] # recv a_equal(cubempi2.recv_buf[i0:i0+n0], cubempi1.send_buf[i1:i1+n1]) #----------------------------------------------------- # Generate a sequential field on the cubed-sphere #----------------------------------------------------- f0 = cubegrid0.local_gids.astype('f8') f1 = cubegrid1.local_gids.astype('f8') f2 = cubegrid2.local_gids.astype('f8') #----------------------------------------------------- # Average the element boundary for the spectral element method #----------------------------------------------------- recv_buf0 = np.zeros(cubempi0.recv_buf_size, 'f8') send_buf0 = np.zeros(cubempi0.send_buf_size, 'f8') recv_buf1 = np.zeros(cubempi1.recv_buf_size, 'f8') send_buf1 = np.zeros(cubempi1.send_buf_size, 'f8') recv_buf2 = np.zeros(cubempi2.recv_buf_size, 'f8') send_buf2 = np.zeros(cubempi2.send_buf_size, 'f8') # Prepare to send pre_send(cubempi0, f0, recv_buf0, send_buf0) pre_send(cubempi1, f1, recv_buf1, send_buf1) pre_send(cubempi2, f2, recv_buf2, send_buf2) # Send/Recv rank0, i0, n0 = cubempi0.send_schedule[0] # send 0->1 rank1, i1, n1 = cubempi1.recv_schedule[0] recv_buf1[i1:i1+n1] = send_buf0[i0:i0+n0] rank1, i1, n1 = cubempi1.send_schedule[0] # send 1->0 rank0, i0, n0 = cubempi0.recv_schedule[0] recv_buf0[i0:i0+n0] = send_buf1[i1:i1+n1] rank1, i1, n1 = cubempi0.send_schedule[1] # send 0->2 rank0, i0, n0 = cubempi2.recv_schedule[0] recv_buf2[i0:i0+n0] = send_buf0[i1:i1+n1] rank1, i1, n1 = cubempi2.send_schedule[0] # send 2->0 rank0, i0, n0 = cubempi0.recv_schedule[1] recv_buf0[i0:i0+n0] = send_buf2[i1:i1+n1] rank1, i1, n1 = cubempi1.send_schedule[1] # send 1->2 rank0, i0, n0 = cubempi2.recv_schedule[1] recv_buf2[i0:i0+n0] = send_buf1[i1:i1+n1] rank1, i1, n1 = cubempi2.send_schedule[1] # send 2->1 rank0, i0, n0 = cubempi1.recv_schedule[1] recv_buf1[i0:i0+n0] = send_buf2[i1:i1+n1] # After receive post_recv(cubempi0, f0, recv_buf0) post_recv(cubempi1, f1, recv_buf1) post_recv(cubempi2, f2, recv_buf2) #----------------------------------------------------- # Check if mvps have same values #----------------------------------------------------- fs = [f0, f1, f2] ranks, lids = cubegrid0.ranks, cubegrid0.lids cs_fpath = cs_grid_dpath + "cs_grid_ne{:03d}np{}.nc".format(ne, ngq) cs_ncf = nc.Dataset(cs_fpath, 'r', format='NETCDF4') mvps = cs_ncf.variables['mvps'][:] for seq, mvp in enumerate(mvps): eff_mvp = [k for k in mvp if k != -1] for gid in eff_mvp: rank, lid = ranks[gid], lids[gid] ok_( feq(fs[rank][lid], np.mean(eff_mvp), 15) )