Пример #1
0
    def update_values(self, 
                      intercomm_dictionary = {}):
	log_file = self.logger.handlers[0].baseFilename
        n_oct = self._n_oct
        o_ranges = self._mat.getOwnershipRange()
        b_bound = self._b_bound
        grid = self._proc_g
        # Upper bound octree's id contained.
        up_id_octree = o_ranges[0] + n_oct
        # Octree's ids contained.
        ids_octree_contained = range(o_ranges[0], up_id_octree)
        # Calling "allgather" to obtain data from the corresponding grid,
        # onto the intercommunicators created, not the intracommunicators.
        # http://www.mcs.anl.gov/research/projects/mpi/mpi-standard/mpi-report-1.1/node114.htm#Node117
        # http://mpitutorial.com/tutorials/mpi-broadcast-and-collective-communication/
        # http://www.linux-mag.com/id/1412/
        for key, intercomm in intercomm_dictionary.items():
            # Extending a list with the lists obtained by the other processes
            # of the corresponding intercommunicator.
            self._edg.extend(intercomm.allgather(self._edl))
            self._res_g.extend(intercomm.allgather(self._res_l))
        # Residual evaluation... 
        for index, dictionary in enumerate(self._res_g):
            for center, solution_value in dictionary.items():
                local_idx = self._octree.get_point_owner_idx(center)
                global_idx = local_idx + o_ranges[0]

                if global_idx in ids_octree_contained:
                    center_cell_container = self._octree.get_center(local_idx)[:2]
                    location = utilities.points_location(center,
                                                         center_cell_container)
                    neigh_centers, neigh_values = ([] for i in range(0, 2))
                    (neigh_centers, 
		     neigh_values) = self.find_right_neighbours(location ,
                                                        local_idx,
                                                        o_ranges[0])
                    bilinear_value = utilities.bil_interp(center       ,
                                                          neigh_centers,
                                                          neigh_values)
                    insert_mode = PETSc.InsertMode.INSERT_VALUES
                    value = bilinear_value - solution_value
                    self._res.setValue(global_idx, 
                                       value     ,
                                       insert_mode)
        self._res.assemblyBegin()
        self._res.assemblyEnd()

        # "self.__temp_data_global" will be a list of same structures of data,
        # after the "allgather" call; these structures are dictionaries.
        for index, dictionary in enumerate(self._edg):
            for key, center in dictionary.items():
                (x_center, y_center) = center
                into_background = True
                ghost_boundary = False
                if len(key) == 3:
                    ghost_boundary = True
                # We are onto grids of the first level.
                if grid:
                    local_idx = self._octree.get_point_owner_idx((x_center,
                                                                  y_center))
                # We are onto the background grid.
                else:
                    if key[2] == 0:
                        x_center = x_center - key[3]
                    if key[2] == 1:
                        x_center = x_center + key[3]
                    if key[2] == 2:
                        y_center = y_center - key[3]
                    if key[2] == 3:
                        y_center = y_center + key[3]

                    into_background = utilities.check_into_square((x_center, 
                                                         	   y_center)  ,
                                                        	  b_bound     ,
								  self.logger ,
								  log_file)
                    if into_background:
                        # The function "get_point_owner_idx" wants only one argument
                        # so we are passing it a tuple.
                        local_idx = self._octree.get_point_owner_idx((x_center,
                                                                      y_center))
                    # Is this "else" useful? For me no.
                    else:
                        local_idx = self._octree.get_point_owner_idx(center)

                global_idx = local_idx + o_ranges[0]

                if global_idx in ids_octree_contained:
                    # Appending a tuple containing the grid number and
                    # the corresponding octant index.
                    if ghost_boundary:
                        self._eil.append((key[0], key[1], key[2]))
                    else:
                        self._eil.append((key[0], key[1]))
                    if into_background:
                        center_cell_container = self._octree.get_center(local_idx)[:2]
                        location = utilities.points_location((x_center,
                                                              y_center),
                                                              center_cell_container)
                        neigh_centers, neigh_values = ([] for i in range(0, 2))
                        (neigh_centers, neigh_values) = self.find_right_neighbours(location ,
                                                                                   local_idx,
                                                                                   o_ranges[0])
                        solution_value = utilities.bil_interp((x_center, 
                                                               y_center)   ,
                                                              neigh_centers,
                                                              neigh_values)
                    else:
                        solution_value = ExactSolution2D.ExactSolution2D.solution(x_center, 
                                                                  		  y_center)

                    self._evl.append(solution_value)
        # Updating data for each process into "self.__intra_extra_indices_global"
        # and "self.__intra_extra_values_global", calling "allgather" to obtain 
        # data from the corresponding grid onto the intercommunicators created, 
        # not the intracommunicators.
        for key, intercomm in intercomm_dictionary.items():
            self._eig.extend(intercomm.allgather(self._eil))
            self._evg.extend(intercomm.allgather(self._evl))

        for index, values in enumerate(self._eig):
            for position, value in enumerate(values):
                # Check if the global index belong to the process.
                if value[1] in ids_octree_contained:
                    # Check if we are onto the right grid.
                    if value[0] == self._proc_g:
                        intra_extra_value = self._evg[index][position]
                        # Background grid.
                        if grid == 0:
                            insert_mode = PETSc.InsertMode.INSERT_VALUES
                            # Here "insert_mode" does not affect nothing.
                            if len(value) == 3:
                                self._e_array_gb.setValue(value[1],
                                                          intra_extra_value,
                                                          insert_mode)
                            else:
                                self._e_array.setValue(value[1]         , 
                                                       intra_extra_value,
                                                       insert_mode)
                        else:
                            insert_mode = PETSc.InsertMode.ADD_VALUES
                            self._e_array.setValue(value[1]         ,
                                                   intra_extra_value,
                                                   insert_mode)

        self._e_array.assemblyBegin()
        self._e_array.assemblyEnd()
        self._e_array_gb.assemblyBegin()
        self._e_array_gb.assemblyEnd()
        # Resetting structures used for the "allgather" functions.
        self.init_e_structures()
        self.logger.info("Updated  inter_extra_array for comm \"" +
                         str(self._comm.Get_name())               + 
                         "\" and rank \""                         +
                         str(self._comm.Get_rank())               +
                         "\" of grid \""                          +
                         str(self._proc_g)                    	  +
                         "\":\n"                                  +
                         str(self._e_array.getArray()))
Пример #2
0
    def set_b_c(self):
	"""Method to set boundary conditions for the current problem."""

        penalization = self._pen
	log_file = self.logger.handlers[0].baseFilename
        b_bound = self._b_bound
        grid = self._proc_g
        n_oct = self._n_oct
        nfaces = glob.nfaces
        # \"getOwnershipRange()\" gives us the local ranges of the matrix owned
        # by the current process.
        o_ranges = self._mat.getOwnershipRange()
        h = self._h
        h2 = h * h
        is_background = False
	overlapping = self._over_l
        # If we are onto the grid \"0\", we are onto the background grid.
        if not grid:
            is_background = True

        b_indices, b_values = ([] for i in range(0, 2))# Boundary indices/values
        b_centers, b_faces = ([] for i in range(0, 2)) # Boundary centers/faces
        for octant in xrange(0, n_oct):
            # Global index of the current local octant \"octant\".
            g_octant = o_ranges[0] + octant
            py_oct = self._octree.get_octant(octant)
            center  = self._octree.get_center(octant)[:2]

            for face in xrange(0, nfaces):
                # If we have an edge on the boundary.
                if self._octree.get_bound(py_oct, 
                                          face):
                    b_indices.append(g_octant)
                    b_faces.append(face)
                    b_centers.append(center)
            
        b_values = self.eval_b_c(b_centers,
                                 b_faces)

	b_values = b_values.tolist()

        if is_background:
            if overlapping:
                self.over_adds(b_centers,
                               b_faces  ,
                               b_values ,
                               b_indices) 
        # Grids not of the background: equal to number >= 1.
        else:
            for i, center in enumerate(b_centers):
                # Check if foreground grid is inside the background one.
                check = utilities.check_into_square(center     ,
                                          	    b_bound    ,
                                          	    self.logger,
                                          	    log_file)
                if check:
                    # Can't use list as dictionary's keys.
                    # http://stackoverflow.com/questions/7257588/why-cant-i-use-a-list-as-a-dict-key-in-python
                    # https://wiki.python.org/moin/DictionaryKeys
                    key = (grid        , # Grid (0 is for the background grid)
                           b_indices[i], # Global index of the octant
                           b_faces[i]  , # Boundary face
                           h)            # Edge's length
                    # We store the centers of the cells on the boundary.
                    self._edl.update({key : center})
                    b_values[i] = self._e_array.getValue(b_indices[i])
                    # Residual evaluation...
                    sol_value = self._sol.getValue(b_indices[i])
                    self._res_l.update({tuple(center) : sol_value})

	    dups = collections.defaultdict(list)
	    for i, e in enumerate(b_indices):
		dups[e].append(i)

	    # Popped elements.
	    p_els = 0
	    for k, v in sorted(dups.iteritems()):
		if len(v) >= 2:
		    for i in range(1, len(v)):
			b_indices.pop(v[i] - p_els)
			b_values.pop(v[i] - p_els)
		
			p_els = p_els + 1

        b_values[:] = [b_value * (-1/h2) for b_value in b_values]
        insert_mode = PETSc.InsertMode.ADD_VALUES
        self._rhs.setValues(b_indices,
                            b_values ,
                            insert_mode)
        # ATTENTION!! Non using these functions will give you an unassembled
        # vector PETSc.
        self._rhs.assemblyBegin()
        self._rhs.assemblyEnd()
        msg = "Set boundary conditions"
        extra_msg = "of grid \"" + str(self._proc_g) + "\""
        self.log_msg(msg   ,
                     "info",
                     extra_msg)