def scatter_1D(self, positions, values, field, location, add_info): if self.root == True: positions, pos_ind = self.mesh.sortPositionsByMeshes(positions, return_ind=[], surface=True) values = [values[i] for i in pos_ind] add_info = [add_info[i] for i in pos_ind] location = self.mesh.sortIndexByMeshes(location, shift=False) pos = positions.pop(0) val = values.pop(0) info = add_info.pop(0) loc = location.pop(0) for child in self.children: loc_i = copy.copy(location[0]) child.scatter_1D(positions, values, field, location, add_info) array_1D = location_indexes_inv(loc_i, store=False) nonzero = numpy.flatnonzero(field[array_1D]) array_1D = array_1D[nonzero] pos = numpy.append(pos, child.mesh.getPosition( child.mesh.location_sat[nonzero]), axis=0) val = numpy.append(val, field[array_1D]) info = numpy.append(info, child.mesh.direction_sat[nonzero]) if len(self.children) > 0: field[location_indexes_inv(loc, store=False)] *= 0 self.scatter_1D_aux(pos, val, field, loc, info)
def scatter_1D_aux(self, positions, values, field, general_location, add_info, prec=10**(-c.INDEX_PREC)): #Creating 1-1 connection between local satellite nodes and general nodes dic = { loc_i: gen_i for loc_i, gen_i in zip(self.mesh.location_sat, general_location) } #Getting mesh coordinates mc = self.mesh.getIndex(positions) index = mc.astype(int) array = self.mesh.indexToArray(index) #Calcualting array indexes with respect to the whole domain array_gen = [dic[i] for i in array] #Getting the correct indexes for the field array_1D = location_indexes_inv(array_gen, store=False) horizontal = numpy.equal(add_info % 2, 0) vertical = numpy.logical_not(horizontal) dindex = numpy.where(horizontal, mc[:, 0] - index[:, 0], mc[:, 1] - index[:, 1]) filter_1D = dindex > prec #Adapting horizontal and vertical such that n_index works for inner boundaries as well as outer boundaries #mask = numpy.ones_like(add_info, dtype = numpy.bool_) #for boundary in self.mesh.boundaries: # if boundary.type == Inner_2D_Rectangular.type: # mask[numpy.flatnonzero(numpy.isin(array, boundary.location))] = False #horizontal = numpy.logical_or(horizontal, mask) #vertical = numpy.logical_and(vertical, numpy.logical_not(mask)) #n_index = numpy.where(horizontal, array_1D+1, array_1D+2) #n_index = numpy.where(numpy.logical_and(vertical, array_1D == 0), n_index-2+self.mesh.nxsat, n_index) #n_index = numpy.where(numpy.logical_and(vertical, array_1D == len(self.mesh.location_sat)-1-self.mesh.nxsat), n_index-2+self.mesh.nxsat, n_index) # Finding the other node involved temp_location_indexes_inv = { locations: indexes[0] for indexes, locations in numpy.ndenumerate(self.mesh.location_sat) } loc_ind = numpy.asarray( [temp_location_indexes_inv.get(ind_i) for ind_i in array], dtype=numpy.uint16) n_index = [ self.mesh.adjacent_sat[loc_ind[i]][add_info[i]] for i in range(len(array_1D)) ] n_index = location_indexes_inv( [dic[self.mesh.location_sat[ind]] for ind in n_index], store=False) #scatter process numpy.add.at(field, array_1D, (1 - dindex) * values) numpy.add.at(field, n_index[filter_1D], dindex[filter_1D] * values[filter_1D])
def scatter_1D(self, positions, values, field, location, add_info, prec=10**(-c.INDEX_PREC)): #Getting mesh coordinates mc = self.mesh.getIndex(positions) index = mc.astype(int) array = self.mesh.indexToArray(index) array_1D = location_indexes_inv(array, store=False) horizontal = numpy.equal(add_info % 2, 0) vertical = numpy.logical_not(horizontal) dindex = numpy.where(horizontal, mc[:, 0] - index[:, 0], mc[:, 1] - index[:, 1]) #n_index = numpy.where(horizontal, array_1D+1, array_1D+2) #n_index = numpy.where(numpy.logical_and(vertical, array_1D == 0), n_index-2+self.mesh.nxsat, n_index) #n_index = numpy.where(numpy.logical_and(vertical, array_1D == len(location)-1-self.mesh.nxsat), n_index-2+self.mesh.nxsat, n_index) n_index = numpy.asarray([ self.mesh.adjacent_sat[array_1D[i]][add_info[i]] for i in range(len(array_1D)) ], dtype=numpy.uint16) filter_i = dindex > prec values = values * numpy.ones_like( (dindex)) if type(values) != numpy.ndarray else values numpy.add.at(field, array_1D, (1 - dindex) * values) numpy.add.at(field, n_index[filter_i], dindex[filter_i] * values[filter_i])
def createDistributionAtBorder(self, location, part_solver, species, delta_n, prec=1e-5): add_rand = numpy.random.rand(len(location)) #This needs to be generalized later #NOTE: Modified(2021/02/14) with no backward compatibility local_loc = location_indexes_inv(location, store=False) mpf_new = delta_n * self.areas[local_loc] #Treating borders mpf_new /= numpy.where( numpy.max(part_solver.pic.mesh.volumes) / part_solver.pic.mesh.volumes[location] > 3, 2, 1) #Computing number of particles created mpf_new = mpf_new / species.spwt + species.mesh_values.residuals[ location] + add_rand mp_new = mpf_new.astype(int) species.mesh_values.residuals[location] = mpf_new - mp_new #Assigning positions pos_1 = numpy.repeat(part_solver.pic.mesh.getPosition(location), mp_new, axis=0) random = numpy.random.rand(numpy.shape(pos_1)[0]) random += numpy.where(random == 0, 1e-3, 0) hit_1 = numpy.repeat(self.directions[local_loc], mp_new) ind_b = numpy.flatnonzero(hit_1 == 0) ind_l = numpy.flatnonzero(hit_1 == 3) ind_r = numpy.flatnonzero(hit_1 == 1) ind_t = numpy.flatnonzero(hit_1 == 2) #Bottom shifts = numpy.where( numpy.abs(pos_1[ind_b, 0] - self.xmin) < prec, random[ind_b] * part_solver.pic.mesh.dx / 2, (random[ind_b] - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[ind_b, 1] - self.xmax) < prec, random[ind_b] * part_solver.pic.mesh.dx / 2, 0) pos_1[ind_b, 0] += shifts #Left shifts = numpy.where( numpy.abs(pos_1[ind_l, 1] - self.ymin) < prec, random[ind_l] * part_solver.pic.mesh.dy / 2, (random[ind_l] - 0.5) * part_solver.pic.mesh.dy) shifts -= numpy.where( numpy.abs(pos_1[ind_l, 1] - self.ymax) < prec, random[ind_l] * part_solver.pic.mesh.dy / 2, 0) pos_1[ind_l, 1] += shifts #Right shifts = numpy.where( numpy.abs(pos_1[ind_r, 1] - self.ymin) < prec, random[ind_r] * part_solver.pic.mesh.dy / 2, (random[ind_r] - 0.5) * part_solver.pic.mesh.dy) shifts -= numpy.where( numpy.abs(pos_1[ind_r, 1] - self.ymax) < prec, random[ind_r] * part_solver.pic.mesh.dy / 2, 0) pos_1[ind_r, 1] += shifts #Top shifts = numpy.where( numpy.abs(pos_1[ind_t, 0] - self.xmin) < prec, random[ind_t] * part_solver.pic.mesh.dx / 2, (random[ind_t] - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[ind_t, 1] - self.xmax) < prec, random[ind_t] * part_solver.pic.mesh.dx / 2, 0) pos_1[ind_t, 0] += shifts repeats = numpy.ones(numpy.shape(hit_1)[0], dtype=numpy.uint8) return (numpy.append(pos_1, hit_1[:, None], axis=1), ), repeats
def createDistributionAtBorder(self, location, part_solver, species, delta_n, prec=1e-5): add_rand = numpy.random.rand(len(location)) #NOTE: this should be generalized if self.material != 'space': local_loc = location_indexes_inv(location, store=False) else: c = 0 local_loc = [] for index, loc in numpy.ndenumerate(self.location): if loc == location[c]: local_loc.append(index[0]) c += 1 local_loc = numpy.asarray(local_loc, dtype='uint32') mpf_new = delta_n * self.areas[local_loc] mpf_new = mpf_new / species.spwt + species.mesh_values.residuals[ location] + add_rand mp_new = mpf_new.astype(int) species.mesh_values.residuals[location] = mpf_new - mp_new #Assigning positions pos_1 = numpy.repeat(part_solver.pic.mesh.getPosition(location), mp_new, axis=0) random = numpy.random.rand(numpy.shape(pos_1)[0]) #Bottom if self.directions[local_loc[0]] == 0: shifts = numpy.where( numpy.abs(pos_1[:, 0] - self.xmin) < prec, random * part_solver.pic.mesh.dx / 2, (random - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[:, 0] - self.xmax) < prec, random * part_solver.pic.mesh.dx / 2, 0) pos_1[:, 0] += shifts hit_1 = numpy.zeros_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] #Left elif self.directions[local_loc[0]] == 3: shifts = numpy.where( numpy.abs(pos_1[:, 1] - self.ymin) < prec, random * part_solver.pic.mesh.dy / 2, (random - 0.5) * part_solver.pic.mesh.dy) shifts -= numpy.where( numpy.abs(pos_1[:, 1] - self.ymax) < prec, random * part_solver.pic.mesh.dy / 2, 0) pos_1[:, 1] += shifts hit_1 = 3 * numpy.ones_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] #Right elif self.directions[local_loc[0]] == 1: shifts = numpy.where( numpy.abs(pos_1[:, 1] - self.ymin) < prec, random * part_solver.pic.mesh.dy / 2, (random - 0.5) * part_solver.pic.mesh.dy) shifts -= numpy.where( numpy.abs(pos_1[:, 1] - self.ymax) < prec, random * part_solver.pic.mesh.dy / 2, 0) pos_1[:, 1] += shifts hit_1 = numpy.ones_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] #Top else: shifts = numpy.where( numpy.abs(pos_1[:, 0] - self.xmin) < prec, random * part_solver.pic.mesh.dx / 2, (random - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[:, 0] - self.xmax) < prec, random * part_solver.pic.mesh.dx / 2, 0) pos_1[:, 0] += shifts hit_1 = 2 * numpy.ones_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] repeats = numpy.ones(numpy.shape(hit_1)[0], dtype=numpy.uint8) return (numpy.append(pos_1, hit_1, axis=1), ), repeats
def createDistributionAtBorder(self, location, part_solver, species, delta_n, prec=1e-5): #This needs to be generalized later #NOTE: Modified(2021/02/14) with no backward compatibility local_loc = location_indexes_inv(location, store=False) mpf_new = delta_n * self.areas[local_loc] #Treating borders y = (numpy.arange(part_solver.pic.mesh.nPoints) // part_solver.pic. mesh.nx) * part_solver.pic.mesh.dy + part_solver.pic.mesh.ymin if part_solver.pic.mesh.ymin == 0.0: y[:part_solver.pic.mesh.nx] = part_solver.pic.mesh.dy / 8 dv = 2 * numpy.pi * y * part_solver.pic.mesh.dy * part_solver.pic.mesh.dx mpf_new /= numpy.where( numpy.abs(dv[location] / part_solver.pic.mesh.volumes[location] - 2) > 1e-3, 2, 1) #Computing number of particles created add_rand = numpy.random.rand(len(location)) mpf_new = mpf_new / species.spwt + species.mesh_values.residuals[ location] + add_rand mp_new = mpf_new.astype(int) species.mesh_values.residuals[location] = mpf_new - mp_new #Assigning positions pos = part_solver.pic.mesh.getPosition(location) pos_1 = numpy.repeat(pos, mp_new, axis=0) hit_1 = self.directions[local_loc] ind_b = hit_1 == 0 ind_l = hit_1 == 3 ind_r = hit_1 == 1 ind_t = hit_1 == 2 #Bottom random = numpy.random.rand(numpy.sum(mp_new[ind_b])) random += numpy.where(random == 0, 1e-3, 0) ind = numpy.repeat(ind_b, mp_new) shifts = numpy.where( numpy.abs(pos_1[ind, 0] - self.xmin) < prec, random * part_solver.pic.mesh.dx / 2, (random - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[ind, 0] - self.xmax) < prec, random * part_solver.pic.mesh.dx / 2, 0) pos_1[ind, 0] += shifts #Left rmin = numpy.where(pos[ind_l, 1] == self.ymin, pos[ind_l, 1], pos[ind_l, 1] - part_solver.pic.mesh.dy / 2) rmax = numpy.where(pos[ind_l, 1] == self.ymax, pos[ind_l, 1], pos[ind_l, 1] + part_solver.pic.mesh.dy / 2) pos_1[numpy.repeat(ind_l, mp_new), 1] = cmt.randomYPositions_2D_cm(mp_new[ind_l], rmin, rmax) #Right rmin = numpy.where(pos[ind_r, 1] == self.ymin, pos[ind_r, 1], pos[ind_r, 1] - part_solver.pic.mesh.dy / 2) rmax = numpy.where(pos[ind_r, 1] == self.ymax, pos[ind_r, 1], pos[ind_r, 1] + part_solver.pic.mesh.dy / 2) pos_1[numpy.repeat(ind_r, mp_new), 1] = cmt.randomYPositions_2D_cm(mp_new[ind_r], rmin, rmax) #Top random = numpy.random.rand(numpy.sum(mp_new[ind_t])) random += numpy.where(random == 0, 1e-3, 0) ind = numpy.repeat(ind_t, mp_new) shifts = numpy.where( numpy.abs(pos_1[ind, 0] - self.xmin) < prec, random * part_solver.pic.mesh.dx / 2, (random - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[ind, 0] - self.xmax) < prec, random * part_solver.pic.mesh.dx / 2, 0) pos_1[ind, 0] += shifts hit_1 = numpy.repeat(hit_1, mp_new) repeats = numpy.ones(numpy.shape(hit_1)[0], dtype=numpy.uint8) return (numpy.append(pos_1, hit_1[:, None], axis=1), ), repeats
def createDistributionAtBorder(self, location, part_solver, species, delta_n, prec=1e-5): add_rand = numpy.random.rand(len(location)) local_loc = location_indexes_inv(location, store=False) mpf_new = delta_n * part_solver.pic.mesh.area_sat[local_loc] mpf_new = mpf_new / species.spwt + species.mesh_values.residuals[ location] + add_rand mp_new = mpf_new.astype(int) species.mesh_values.residuals[location] = mpf_new - mp_new #Assigning positions pos_1 = numpy.repeat(part_solver.pic.mesh.getPosition(location), mp_new, axis=0) random = numpy.random.rand(numpy.shape(pos_1)[0]) #Bottom if self.directions[local_loc[0]] == 0: shifts = numpy.where( numpy.abs(pos_1[:, 0] - self.xmin) < prec, random * part_solver.pic.mesh.dx / 2, (random - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[:, 0] - self.xmax) < prec, random * part_solver.pic.mesh.dx / 2, 0) pos_1[:, 0] += shifts hit_1 = numpy.zeros_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] #Left elif self.directions[local_loc[0]] == 3: shifts = numpy.where( numpy.abs(pos_1[:, 1] - self.ymin) < prec, random * part_solver.pic.mesh.dy / 2, (random - 0.5) * part_solver.pic.mesh.dy) shifts -= numpy.where( numpy.abs(pos_1[:, 1] - self.ymax) < prec, random * part_solver.pic.mesh.dy / 2, 0) pos_1[:, 1] += shifts hit_1 = 3 * numpy.ones_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] #Right elif self.directions[local_loc[0]] == 1: shifts = numpy.where( numpy.abs(pos_1[:, 1] - self.ymin) < prec, random * part_solver.pic.mesh.dy / 2, (random - 0.5) * part_solver.pic.mesh.dy) shifts -= numpy.where( numpy.abs(pos_1[:, 1] - self.ymax) < prec, random * part_solver.pic.mesh.dy / 2, 0) pos_1[:, 1] += shifts hit_1 = numpy.ones_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] #Top else: shifts = numpy.where( numpy.abs(pos_1[:, 0] - self.xmin) < prec, random * part_solver.pic.mesh.dx / 2, (random - 0.5) * part_solver.pic.mesh.dx) shifts -= numpy.where( numpy.abs(pos_1[:, 0] - self.xmax) < prec, random * part_solver.pic.mesh.dx / 2, 0) pos_1[:, 0] += shifts hit_1 = 2 * numpy.ones_like(pos_1[:, 1], dtype=numpy.uint8)[:, None] repeats = numpy.ones(numpy.shape(hit_1)[0], dtype=numpy.uint8) return (numpy.append(pos_1, hit_1, axis=1), ), repeats