def make_remap_matrix(self, debug=False):
        dst_obj = self.dst_obj
        src_obj = self.src_obj

        dsw_dict = dict()       # {dst:[(s,w),(s,w),...],...}
        if debug: ipoly_dict = dict()  # {dst:[(src,ipoly,iarea),...],..}
        
        for dst, (lat0,lon0) in enumerate(dst_obj.latlons):
            dst_poly = dst_obj.get_voronoi(dst)
            dst_area = area_polygon(dst_poly)
            inout = pt_in_polygon(dst_poly, latlon2xyz(lat0,lon0))
            if inout != 'in':
                print('dst',dst)
                print('latlon_in_poly?', inout)

            idx1, idx2, idx3, idx4 = src_obj.get_surround_idxs(lat0, lon0)
            candidates = set([idx1, idx2, idx3, idx4])
            if -1 in candidates: candidates.remove(-1)
            checked_srcs = set()

            dsw_dict[dst] = list()
            while len(candidates) > 0:
                #print('\t', checked_srcs)
                src = candidates.pop()
                src_poly = src_obj.get_voronoi(src)

                ipoly = intersect_two_polygons(dst_poly, src_poly)
                checked_srcs.add(src)

                if ipoly != None:
                    iarea = area_polygon(ipoly)
                    area_ratio = iarea/dst_area

                    if area_ratio > 1e-10:
                        dsw_dict[dst].append( (src, area_ratio) )
                        nbrs = set(src_obj.get_neighbors(src))
                        candidates.update(nbrs - checked_srcs)

                        if debug: ipoly_dict[dst].append( (src,ipoly,iarea) )

        if debug: self.save_netcdf_ipoly(ipoly_dict)

        return self.make_remap_matrix_from_dsw_dict(dsw_dict)
    def make_remap_matrix_mpi(self, debug=False):
        from mpi4py import MPI

        comm = MPI.COMM_WORLD
        nproc = comm.Get_size()
        myrank = comm.Get_rank()

        if nproc == 1:
            return self.make_remap_matrix()


        dst_obj = self.dst_obj
        src_obj = self.src_obj
        chunk_size = dst_obj.nsize//nproc//10

        dsw_dict = dict()       # {dst:[(src,wgt),(src,wgt),...],...}

        if debug:
            ipoly_dict = dict()  # {dst:[(src,ipoly,iarea),...],..}
        

        if myrank == 0:
            start = 0
            while start < dst_obj.nsize:
                rank = comm.recv(source=MPI.ANY_SOURCE, tag=0)
                comm.send(start, dest=rank, tag=10)
                start += chunk_size

            for i in range(nproc-1):
                rank = comm.recv(source=MPI.ANY_SOURCE, tag=0)
                comm.send('quit', dest=rank, tag=10)

                slave_dsw_dict = comm.recv(source=rank, tag=20)
                dsw_dict.update(slave_dsw_dict)

                if debug:
                    slave_ipoly_dict = comm.recv(source=rank, tag=30)
                    ipoly_dict.update(slave_src_poly_dict)
                    self.save_netcdf_ipoly(ipoly_dict)

            return self.make_remap_matrix_from_dsw_dict(dsw_dict)

        else:
            while True:
                comm.send(myrank, dest=0, tag=0)
                msg = comm.recv(source=0, tag=10)

                if msg == 'quit':
                    print("Slave rank {} quit.".format(myrank))
                    comm.send(dsw_dict, dest=0, tag=20)

                    if debug:
                        comm.send(ipoly_dict, dest=0, tag=30)

                    return None, None, None

                start = msg
                end = start + chunk_size
                end = dst_obj.nsize if end > dst_obj.nsize else end
                print("rank {}: {} ~ {} ({} %%)".format(myrank, start, end, end/dst_obj.nsize*100))

                for dst in range(start,end):
                    lat0, lon0 = dst_obj.latlons[dst]
                    dst_poly = dst_obj.get_voronoi(dst)
                    dst_area = area_polygon(dst_poly)

                    idx1, idx2, idx3, idx4 = src_obj.get_surround_idxs(lat0, lon0)
                    candidates = set([idx1, idx2, idx3, idx4])
                    if -1 in candidates: candidates.remove(-1)
                    checked_srcs = set()

                    dsw_dict[dst] = list()

                    if debug:
                        ipoly_dict[dst] = list()

                    while len(candidates) > 0:
                        src = candidates.pop()
                        src_poly = src_obj.get_voronoi(src)

                        ipoly = intersect_two_polygons(dst_poly, src_poly)
                        checked_srcs.add(src)

                        if ipoly != None:
                            iarea = area_polygon(ipoly)
                            area_ratio = iarea/dst_area

                            if area_ratio > 1e-10:
                                dsw_dict[dst].append( (src, area_ratio) )
                                nbrs = set(src_obj.get_neighbors(src))
                                candidates.update(nbrs - checked_srcs)

                                if debug:
                                    ipoly_dict[dst].append( (src,ipoly,iarea) )