[1461] | 1 | import sys |
---|
| 2 | from os import sep |
---|
| 3 | sys.path.append('..'+sep+'pyvolution') |
---|
| 4 | |
---|
| 5 | """parallel-meshes - |
---|
| 6 | 2D triangular domains for parallel finite-volume computations of |
---|
| 7 | the advection equation, with extra structures to define the |
---|
| 8 | sending and receiving communications define in dictionaries |
---|
| 9 | full_send_dict and ghost_recv_dict |
---|
| 10 | |
---|
| 11 | |
---|
| 12 | Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou |
---|
| 13 | Geoscience Australia, 2005 |
---|
[2625] | 14 | |
---|
| 15 | Modified by Linda Stals, March 2006, to include ghost boundaries |
---|
| 16 | |
---|
[1461] | 17 | """ |
---|
| 18 | |
---|
[1607] | 19 | #from parallel_advection import * |
---|
[1461] | 20 | |
---|
[1607] | 21 | import pypar |
---|
| 22 | from Numeric import array |
---|
[1461] | 23 | |
---|
[1563] | 24 | def parallel_rectangle(m_g, n_g, len1_g=1.0, len2_g=1.0, origin_g = (0.0, 0.0)): |
---|
[1461] | 25 | |
---|
| 26 | |
---|
| 27 | """Setup a rectangular grid of triangles |
---|
| 28 | with m+1 by n+1 grid points |
---|
| 29 | and side lengths len1, len2. If side lengths are omitted |
---|
| 30 | the mesh defaults to the unit square, divided between all the |
---|
| 31 | processors |
---|
| 32 | |
---|
| 33 | len1: x direction (left to right) |
---|
| 34 | len2: y direction (bottom to top) |
---|
| 35 | |
---|
| 36 | """ |
---|
| 37 | |
---|
| 38 | from config import epsilon |
---|
| 39 | from Numeric import zeros, Float, Int |
---|
| 40 | |
---|
| 41 | processor = pypar.rank() |
---|
| 42 | numproc = pypar.size() |
---|
| 43 | |
---|
[1520] | 44 | m_low, m_high = pypar.balance(m_g, numproc, processor) |
---|
[1461] | 45 | |
---|
[1520] | 46 | n = n_g |
---|
| 47 | m_low = m_low-1 |
---|
| 48 | m_high = m_high+1 |
---|
| 49 | m = m_high - m_low |
---|
[1461] | 50 | |
---|
[1520] | 51 | delta1 = float(len1_g)/m_g |
---|
| 52 | delta2 = float(len2_g)/n_g |
---|
[1461] | 53 | |
---|
[1520] | 54 | len1 = len1_g*float(m)/float(m_g) |
---|
| 55 | len2 = len2_g |
---|
| 56 | origin = ( origin_g[0]+float(m_low)/float(m_g)*len1_g, origin_g[1] ) |
---|
| 57 | |
---|
| 58 | |
---|
[1461] | 59 | #Calculate number of points |
---|
| 60 | Np = (m+1)*(n+1) |
---|
| 61 | |
---|
| 62 | class VIndex: |
---|
| 63 | |
---|
| 64 | def __init__(self, n,m): |
---|
| 65 | self.n = n |
---|
| 66 | self.m = m |
---|
| 67 | |
---|
| 68 | def __call__(self, i,j): |
---|
| 69 | return j+i*(self.n+1) |
---|
| 70 | |
---|
| 71 | class EIndex: |
---|
| 72 | |
---|
| 73 | def __init__(self, n,m): |
---|
| 74 | self.n = n |
---|
| 75 | self.m = m |
---|
| 76 | |
---|
| 77 | def __call__(self, i,j): |
---|
| 78 | return 2*(j+i*self.n) |
---|
| 79 | |
---|
| 80 | |
---|
| 81 | I = VIndex(n,m) |
---|
| 82 | E = EIndex(n,m) |
---|
| 83 | |
---|
| 84 | points = zeros( (Np,2), Float) |
---|
| 85 | |
---|
| 86 | for i in range(m+1): |
---|
| 87 | for j in range(n+1): |
---|
| 88 | |
---|
| 89 | points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]] |
---|
| 90 | |
---|
| 91 | #Construct 2 triangles per rectangular element and assign tags to boundary |
---|
| 92 | #Calculate number of triangles |
---|
| 93 | Nt = 2*m*n |
---|
| 94 | |
---|
| 95 | |
---|
| 96 | elements = zeros( (Nt,3), Int) |
---|
| 97 | boundary = {} |
---|
| 98 | Idgl = [] |
---|
| 99 | Idfl = [] |
---|
| 100 | Idgr = [] |
---|
| 101 | Idfr = [] |
---|
| 102 | |
---|
| 103 | full_send_dict = {} |
---|
| 104 | ghost_recv_dict = {} |
---|
| 105 | nt = -1 |
---|
| 106 | for i in range(m): |
---|
| 107 | for j in range(n): |
---|
| 108 | |
---|
| 109 | i1 = I(i,j+1) |
---|
| 110 | i2 = I(i,j) |
---|
| 111 | i3 = I(i+1,j+1) |
---|
| 112 | i4 = I(i+1,j) |
---|
| 113 | |
---|
| 114 | #Lower Element |
---|
| 115 | nt = E(i,j) |
---|
| 116 | if i == 0: |
---|
| 117 | Idgl.append(nt) |
---|
| 118 | |
---|
| 119 | if i == 1: |
---|
| 120 | Idfl.append(nt) |
---|
| 121 | |
---|
| 122 | if i == m-2: |
---|
| 123 | Idfr.append(nt) |
---|
| 124 | |
---|
| 125 | if i == m-1: |
---|
| 126 | Idgr.append(nt) |
---|
| 127 | |
---|
| 128 | if i == m-1: |
---|
[2625] | 129 | if processor == numproc-1: |
---|
| 130 | boundary[nt, 2] = 'right' |
---|
| 131 | else: |
---|
| 132 | boundary[nt, 2] = 'ghost' |
---|
| 133 | |
---|
[1461] | 134 | if j == 0: |
---|
| 135 | boundary[nt, 1] = 'bottom' |
---|
| 136 | elements[nt,:] = [i4,i3,i2] |
---|
| 137 | |
---|
| 138 | #Upper Element |
---|
| 139 | nt = E(i,j)+1 |
---|
| 140 | if i == 0: |
---|
| 141 | Idgl.append(nt) |
---|
| 142 | |
---|
| 143 | if i == 1: |
---|
| 144 | Idfl.append(nt) |
---|
| 145 | |
---|
| 146 | if i == m-2: |
---|
| 147 | Idfr.append(nt) |
---|
| 148 | |
---|
| 149 | if i == m-1: |
---|
| 150 | Idgr.append(nt) |
---|
| 151 | |
---|
| 152 | if i == 0: |
---|
[2625] | 153 | if processor == 0: |
---|
| 154 | boundary[nt, 2] = 'left' |
---|
| 155 | else: |
---|
| 156 | boundary[nt, 2] = 'ghost' |
---|
[1461] | 157 | if j == n-1: |
---|
| 158 | boundary[nt, 1] = 'top' |
---|
| 159 | elements[nt,:] = [i1,i2,i3] |
---|
| 160 | |
---|
| 161 | if numproc==1: |
---|
| 162 | Idfl.extend(Idfr) |
---|
| 163 | Idgr.extend(Idgl) |
---|
| 164 | Idfl = array(Idfl,Int) |
---|
| 165 | Idgr = array(Idgr,Int) |
---|
[1563] | 166 | full_send_dict[processor] = [Idfl, Idfl] |
---|
| 167 | ghost_recv_dict[processor] = [Idgr, Idgr] |
---|
[1461] | 168 | elif numproc == 2: |
---|
| 169 | Idfl.extend(Idfr) |
---|
| 170 | Idgr.extend(Idgl) |
---|
| 171 | Idfl = array(Idfl,Int) |
---|
| 172 | Idgr = array(Idgr,Int) |
---|
[1563] | 173 | full_send_dict[(processor-1)%numproc] = [Idfl, Idfl] |
---|
| 174 | ghost_recv_dict[(processor-1)%numproc] = [Idgr, Idgr] |
---|
[1461] | 175 | else: |
---|
| 176 | Idfl = array(Idfl,Int) |
---|
| 177 | Idgl = array(Idgl,Int) |
---|
| 178 | |
---|
| 179 | Idfr = array(Idfr,Int) |
---|
| 180 | Idgr = array(Idgr,Int) |
---|
| 181 | |
---|
[1563] | 182 | full_send_dict[(processor-1)%numproc] = [Idfl, Idfl] |
---|
| 183 | ghost_recv_dict[(processor-1)%numproc] = [Idgl, Idgl] |
---|
| 184 | full_send_dict[(processor+1)%numproc] = [Idfr, Idfr] |
---|
| 185 | ghost_recv_dict[(processor+1)%numproc] = [Idgr, Idgr] |
---|
[1461] | 186 | |
---|
| 187 | return points, elements, boundary, full_send_dict, ghost_recv_dict |
---|
| 188 | |
---|
| 189 | |
---|
| 190 | |
---|
| 191 | def rectangular_periodic(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)): |
---|
| 192 | |
---|
| 193 | |
---|
| 194 | """Setup a rectangular grid of triangles |
---|
| 195 | with m+1 by n+1 grid points |
---|
| 196 | and side lengths len1, len2. If side lengths are omitted |
---|
| 197 | the mesh defaults to the unit square. |
---|
| 198 | |
---|
| 199 | len1: x direction (left to right) |
---|
| 200 | len2: y direction (bottom to top) |
---|
| 201 | |
---|
| 202 | Return to lists: points and elements suitable for creating a Mesh or |
---|
| 203 | FVMesh object, e.g. Mesh(points, elements) |
---|
| 204 | """ |
---|
| 205 | |
---|
| 206 | from config import epsilon |
---|
| 207 | from Numeric import zeros, Float, Int |
---|
| 208 | |
---|
| 209 | delta1 = float(len1)/m |
---|
| 210 | delta2 = float(len2)/n |
---|
| 211 | |
---|
| 212 | #Calculate number of points |
---|
| 213 | Np = (m+1)*(n+1) |
---|
| 214 | |
---|
| 215 | class VIndex: |
---|
| 216 | |
---|
| 217 | def __init__(self, n,m): |
---|
| 218 | self.n = n |
---|
| 219 | self.m = m |
---|
| 220 | |
---|
| 221 | def __call__(self, i,j): |
---|
| 222 | return j+i*(self.n+1) |
---|
| 223 | |
---|
| 224 | class EIndex: |
---|
| 225 | |
---|
| 226 | def __init__(self, n,m): |
---|
| 227 | self.n = n |
---|
| 228 | self.m = m |
---|
| 229 | |
---|
| 230 | def __call__(self, i,j): |
---|
| 231 | return 2*(j+i*self.n) |
---|
| 232 | |
---|
| 233 | |
---|
| 234 | I = VIndex(n,m) |
---|
| 235 | E = EIndex(n,m) |
---|
| 236 | |
---|
| 237 | points = zeros( (Np,2), Float) |
---|
| 238 | |
---|
| 239 | for i in range(m+1): |
---|
| 240 | for j in range(n+1): |
---|
| 241 | |
---|
| 242 | points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]] |
---|
| 243 | |
---|
| 244 | #Construct 2 triangles per rectangular element and assign tags to boundary |
---|
| 245 | #Calculate number of triangles |
---|
| 246 | Nt = 2*m*n |
---|
| 247 | |
---|
| 248 | |
---|
| 249 | elements = zeros( (Nt,3), Int) |
---|
| 250 | boundary = {} |
---|
| 251 | ghosts = {} |
---|
| 252 | nt = -1 |
---|
| 253 | for i in range(m): |
---|
| 254 | for j in range(n): |
---|
| 255 | |
---|
| 256 | i1 = I(i,j+1) |
---|
| 257 | i2 = I(i,j) |
---|
| 258 | i3 = I(i+1,j+1) |
---|
| 259 | i4 = I(i+1,j) |
---|
| 260 | |
---|
| 261 | #Lower Element |
---|
| 262 | nt = E(i,j) |
---|
| 263 | if i == m-1: |
---|
| 264 | ghosts[nt] = E(1,j) |
---|
| 265 | if i == 0: |
---|
| 266 | ghosts[nt] = E(m-2,j) |
---|
| 267 | |
---|
| 268 | if j == n-1: |
---|
| 269 | ghosts[nt] = E(i,1) |
---|
| 270 | |
---|
| 271 | if j == 0: |
---|
| 272 | ghosts[nt] = E(i,n-2) |
---|
| 273 | |
---|
| 274 | if i == m-1: |
---|
[2625] | 275 | if processor == numproc-1: |
---|
| 276 | boundary[nt, 2] = 'right' |
---|
| 277 | else: |
---|
| 278 | boundary[nt, 2] = 'ghost' |
---|
[1461] | 279 | if j == 0: |
---|
| 280 | boundary[nt, 1] = 'bottom' |
---|
| 281 | elements[nt,:] = [i4,i3,i2] |
---|
| 282 | |
---|
| 283 | #Upper Element |
---|
| 284 | nt = E(i,j)+1 |
---|
| 285 | if i == m-1: |
---|
| 286 | ghosts[nt] = E(1,j)+1 |
---|
| 287 | if i == 0: |
---|
| 288 | ghosts[nt] = E(m-2,j)+1 |
---|
| 289 | |
---|
| 290 | if j == n-1: |
---|
| 291 | ghosts[nt] = E(i,1)+1 |
---|
| 292 | |
---|
| 293 | if j == 0: |
---|
| 294 | ghosts[nt] = E(i,n-2)+1 |
---|
| 295 | |
---|
| 296 | if i == 0: |
---|
[2625] | 297 | if processor == 0: |
---|
| 298 | boundary[nt, 2] = 'left' |
---|
| 299 | else: |
---|
| 300 | boundary[nt, 2] = 'ghost' |
---|
[1461] | 301 | if j == n-1: |
---|
| 302 | boundary[nt, 1] = 'top' |
---|
| 303 | elements[nt,:] = [i1,i2,i3] |
---|
| 304 | |
---|
| 305 | #bottom left |
---|
| 306 | nt = E(0,0) |
---|
| 307 | nf = E(m-2,n-2) |
---|
| 308 | ghosts[nt] = nf |
---|
| 309 | ghosts[nt+1] = nf+1 |
---|
| 310 | |
---|
| 311 | #bottom right |
---|
| 312 | nt = E(m-1,0) |
---|
| 313 | nf = E(1,n-2) |
---|
| 314 | ghosts[nt] = nf |
---|
| 315 | ghosts[nt+1] = nf+1 |
---|
| 316 | |
---|
| 317 | #top left |
---|
| 318 | nt = E(0,n-1) |
---|
| 319 | nf = E(m-2,1) |
---|
| 320 | ghosts[nt] = nf |
---|
| 321 | ghosts[nt+1] = nf+1 |
---|
| 322 | |
---|
| 323 | #top right |
---|
| 324 | nt = E(m-1,n-1) |
---|
| 325 | nf = E(1,1) |
---|
| 326 | ghosts[nt] = nf |
---|
| 327 | ghosts[nt+1] = nf+1 |
---|
| 328 | |
---|
| 329 | return points, elements, boundary, ghosts |
---|
| 330 | |
---|
| 331 | def rectangular_periodic_lr(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)): |
---|
| 332 | |
---|
| 333 | |
---|
| 334 | """Setup a rectangular grid of triangles |
---|
| 335 | with m+1 by n+1 grid points |
---|
| 336 | and side lengths len1, len2. If side lengths are omitted |
---|
| 337 | the mesh defaults to the unit square. |
---|
| 338 | |
---|
| 339 | len1: x direction (left to right) |
---|
| 340 | len2: y direction (bottom to top) |
---|
| 341 | |
---|
| 342 | Return to lists: points and elements suitable for creating a Mesh or |
---|
| 343 | Domain object, e.g. Mesh(points, elements) |
---|
| 344 | """ |
---|
| 345 | |
---|
| 346 | from config import epsilon |
---|
| 347 | from Numeric import zeros, Float, Int |
---|
| 348 | |
---|
| 349 | delta1 = float(len1)/m |
---|
| 350 | delta2 = float(len2)/n |
---|
| 351 | |
---|
| 352 | #Calculate number of points |
---|
| 353 | Np = (m+1)*(n+1) |
---|
| 354 | |
---|
| 355 | class VIndex: |
---|
| 356 | |
---|
| 357 | def __init__(self, n,m): |
---|
| 358 | self.n = n |
---|
| 359 | self.m = m |
---|
| 360 | |
---|
| 361 | def __call__(self, i,j): |
---|
| 362 | return j+i*(self.n+1) |
---|
| 363 | |
---|
| 364 | class EIndex: |
---|
| 365 | |
---|
| 366 | def __init__(self, n,m): |
---|
| 367 | self.n = n |
---|
| 368 | self.m = m |
---|
| 369 | |
---|
| 370 | def __call__(self, i,j): |
---|
| 371 | return 2*(j+i*self.n) |
---|
| 372 | |
---|
| 373 | |
---|
| 374 | I = VIndex(n,m) |
---|
| 375 | E = EIndex(n,m) |
---|
| 376 | |
---|
| 377 | points = zeros( (Np,2), Float) |
---|
| 378 | |
---|
| 379 | for i in range(m+1): |
---|
| 380 | for j in range(n+1): |
---|
| 381 | |
---|
| 382 | points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]] |
---|
| 383 | |
---|
| 384 | #Construct 2 triangles per rectangular element and assign tags to boundary |
---|
| 385 | #Calculate number of triangles |
---|
| 386 | Nt = 2*m*n |
---|
| 387 | |
---|
| 388 | |
---|
| 389 | elements = zeros( (Nt,3), Int) |
---|
| 390 | boundary = {} |
---|
| 391 | ghosts = {} |
---|
| 392 | nt = -1 |
---|
| 393 | for i in range(m): |
---|
| 394 | for j in range(n): |
---|
| 395 | |
---|
| 396 | i1 = I(i,j+1) |
---|
| 397 | i2 = I(i,j) |
---|
| 398 | i3 = I(i+1,j+1) |
---|
| 399 | i4 = I(i+1,j) |
---|
| 400 | |
---|
| 401 | #Lower Element |
---|
| 402 | nt = E(i,j) |
---|
| 403 | if i == m-1: |
---|
| 404 | ghosts[nt] = E(1,j) |
---|
| 405 | if i == 0: |
---|
| 406 | ghosts[nt] = E(m-2,j) |
---|
| 407 | |
---|
| 408 | if i == m-1: |
---|
[2625] | 409 | if processor == numproc-1: |
---|
| 410 | boundary[nt, 2] = 'right' |
---|
| 411 | else: |
---|
| 412 | boundary[nt, 2] = 'ghost' |
---|
[1461] | 413 | if j == 0: |
---|
| 414 | boundary[nt, 1] = 'bottom' |
---|
| 415 | elements[nt,:] = [i4,i3,i2] |
---|
| 416 | |
---|
| 417 | #Upper Element |
---|
| 418 | nt = E(i,j)+1 |
---|
| 419 | if i == m-1: |
---|
| 420 | ghosts[nt] = E(1,j)+1 |
---|
| 421 | if i == 0: |
---|
| 422 | ghosts[nt] = E(m-2,j)+1 |
---|
| 423 | |
---|
| 424 | if i == 0: |
---|
[2625] | 425 | if processor == 0: |
---|
| 426 | boundary[nt, 2] = 'left' |
---|
| 427 | else: |
---|
| 428 | boundary[nt, 2] = 'ghost' |
---|
[1461] | 429 | if j == n-1: |
---|
| 430 | boundary[nt, 1] = 'top' |
---|
| 431 | elements[nt,:] = [i1,i2,i3] |
---|
| 432 | |
---|
| 433 | |
---|
| 434 | return points, elements, boundary, ghosts |
---|