def __init__(self, system, var_idxs, input_idxs,
                 scatter_conns, noflat_vars):
        self.scatter = None
        self.scatter_conns = scatter_conns
        self.noflat_vars = sorted(noflat_vars)

        if not (MPI or scatter_conns or noflat_vars):
            return  # no data to xfer

        try:
            var_idxs, input_idxs = merge_idxs(var_idxs, input_idxs)
        except Exception as err:
            raise RuntimeError("ERROR creating scatter for system %s in scope %s: %s" %
                                (system.name, str(system.scope), str(err)))

        self.var_idxs = to_slice(var_idxs)
        self.input_idxs = to_slice(input_idxs)

        if len(var_idxs) != len(input_idxs):
            raise RuntimeError("ERROR: creating scatter (index size mismatch): (%d != %d) srcs: %s,  dest: %s in %s" %
                                (len(var_idxs), len(input_idxs),
                                  var_idxs, input_idxs, system.name))

        if MPI:
            var_idx_set = PETSc.IS().createGeneral(var_idxs,
                                                   comm=system.mpi.comm)
            input_idx_set = PETSc.IS().createGeneral(input_idxs,
                                                     comm=system.mpi.comm)

            if system.app_ordering is not None:
                var_idx_set = system.app_ordering.app2petsc(var_idx_set)

            try:
                # note that scatter created here can be reused for other vectors as long
                # as their sizes are the same as 'u' and 'p'
                # print "PETSC srcs: %s" % var_idx_set.indices
                # print "PETSC dests: %s" % input_idx_set.indices
                self.scatter = PETSc.Scatter().create(system.vec['u'].petsc_vec, var_idx_set,
                                                      system.vec['p'].petsc_vec, input_idx_set)
            except Exception as err:
                raise RuntimeError("ERROR in %s (var_idxs=%s, input_idxs=%s, usize=%d, psize=%d): %s" %
                                      (system.name, var_idxs, input_idxs, system.vec['u'].array.size,
                                       system.vec['p'].array.size, str(err)))
        else:  # serial execution
            if len(var_idxs) and len(input_idxs):
                self.scatter = SerialScatter(system.vec['u'], var_idxs,
                                             system.vec['p'], input_idxs)
    def _add_subview(self, scope, name):
        var = scope._var_meta[name]
        name2collapsed = scope.name2collapsed

        sz = var['size']
        if sz > 0 and not var.get('noflat'):
            idx = var['flat_idx']
            base = self._info[name2collapsed[var['basevar']]]
            sub_idx = offset_flat_index(idx, base.start)
            substart = get_flat_index_start(sub_idx)
            self._info[name] = ViewInfo(base.view, substart, to_slice(idx),
                                        len(to_indices(idx, base.view)), True)

            if self.array[sub_idx].size != sz:
                raise RuntimeError("size mismatch: in system %s, view for %s is %s, idx=%s, size=%d" %
                                     (system.name, name,
                                     list(self.bounds(name)),
                                     sub_idx,self.array[sub_idx].size))
 def __init__(self, srcvec, src_idxs, destvec, dest_idxs):
     self.src_idxs = to_slice(src_idxs)
     self.dest_idxs = to_slice(dest_idxs)
     self.svec = srcvec
     self.dvec = destvec