// File: /workspace/github_c_makefile_star2_O2/mohuangrui[P]ArtraCFD/domain_partition.c
// Function: PartitionDomain
void PartitionDomain(Space *space)
{
    Partition *const part = &(space->part);
    /*
     * Outward facing surface unit normal vector of domain boundary
     * Surface normal vector can provide great advantage: every surface can
     * be treated uniformly if operations are incorporated with surface
     * normal vector. For example, (NX, NY, NZ) is the outward facing unit
     * normal vector at surface point (i, j, k), then its neighbour node
     * (ih, jh, kh) is more inner than current node if
     * (ih - i) * NX + (jh - j) * NY + (kh - k) * NZ < 0.
     */
    const int N[NBC][DIMS] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0},
        {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
    for (int p = 0; p < NBC; ++p) {
        for (int s = 0; s < DIMS; ++s) {
            part->N[p][s] = N[p][s];
        }
    }
    /*
     * Define the index control array of each partition
     * min and max are used to define domain index range and are widely
     * used in for loop control. To reduce loop comparisons, use a
     * reachable value for min, and unreachable value for max. To count
     * the total valid objects, simply do (max - min).
     *
     * Index range
     * Entire domain (includes exterior ghost): [0, n);
     * Lower exterior ghost: [0, ng);
     * Normal nodes: [ng, n-ng);
     *      Lower boundary: [ng, ng+1);
     *      Interior node layers: [ng+1, n-ng-1);
     *      Upper Boundary: [n-ng-1, n-ng);
     * Upper exterior ghost: [n-ng, n);
     *
     * The computational domain are categorized into three main regions:
     * interior region, boundary region, and ghost region. In general,
     * the interior region is where normal computation is performed;
     * the boundary region is where physical boundary condition is enforced;
     * the ghost region is where numerical boundary treatment is performed.
     *
     * When the periodic boundary condition is applied to a direction, then
     * the interior region in this direction should be extended to include
     * the boundary region, which will then participate normal computation.
     */
    for (int s = 0, q = PWB; s < DIMS; ++s, q = q + 2) {
        /* interior region */
        if (PERIODIC == part->typeBC[q]) { /* extended interior range */
            part->ns[PIN][s][MIN] = part->ng[s];
            part->ns[PIN][s][MAX] = part->n[s] - part->ng[s];
        } else { /* normal interior range */
            part->ns[PIN][s][MIN] = part->ng[s] + 1;
            part->ns[PIN][s][MAX] = part->n[s] - part->ng[s] - 1;
        }
        /* boundary box */
        for (int p = PWB; p <= PBB; ++p) {
            part->ns[p][s][MIN] = part->ng[s];
            part->ns[p][s][MAX] = part->n[s] - part->ng[s];
        }
        /* ghost box */
        for (int p = PWG; p <= PBG; ++p) {
            part->ns[p][s][MIN] = 0;
            part->ns[p][s][MAX] = part->n[s];
        }
        /* physical region */
        part->ns[PHY][s][MIN] = part->ng[s];
        part->ns[PHY][s][MAX] = part->n[s] - part->ng[s];
        /* all region */
        part->ns[PAL][s][MIN] = 0;
        part->ns[PAL][s][MAX] = part->n[s];
    }
    /* adjust boundary box to the boundary region of each direction */
    for (int p = PWB, s = 0; p <= PBB; p = p + 2, ++s) {
        part->ns[p][s][MAX] = part->ns[p][s][MIN] + 1;
    }
    for (int p = PEB, s = 0; p <= PBB; p = p + 2, ++s) {
        part->ns[p][s][MIN] = part->ns[p][s][MAX] - 1;
    }
    /* adjust ghost box to the ghost region of each direction */
    for (int p = PWG, s = 0; p <= PBG; p = p + 2, ++s) {
        part->ns[p][s][MAX] = part->ng[s];
    }
    for (int p = PEG, s = 0; p <= PBG; p = p + 2, ++s) {
        part->ns[p][s][MIN] = part->n[s] - part->ng[s];
    }
    /* computational node range with dimension priority */
    const int np[DIMS][DIMS][LIMIT] = {
        {
            {part->ns[PIN][X][MIN], part->ns[PIN][X][MAX]},
            {part->ns[PIN][Y][MIN], part->ns[PIN][Y][MAX]},
            {part->ns[PIN][Z][MIN], part->ns[PIN][Z][MAX]}
        },
        {
            {part->ns[PIN][Y][MIN], part->ns[PIN][Y][MAX]},
            {part->ns[PIN][X][MIN], part->ns[PIN][X][MAX]},
            {part->ns[PIN][Z][MIN], part->ns[PIN][Z][MAX]}
        },
        {
            {part->ns[PIN][Z][MIN], part->ns[PIN][Z][MAX]},
            {part->ns[PIN][X][MIN], part->ns[PIN][X][MAX]},
            {part->ns[PIN][Y][MIN], part->ns[PIN][Y][MAX]}
        }
    };
    for (int n = 0; n < DIMS; ++n) {
        for (int s = 0; s < DIMS; ++s) {
            for (int m = 0; m < LIMIT; ++m) {
                part->np[n][s][m] = np[n][s][m];
            }
        }
    }
    /* search path for interfacial node */
    const int path[PATHN][DIMS] = { /* searching path */
        {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1},
        {-1, -1, 0}, {1, -1, 0}, {-1, 1, 0}, {1, 1, 0},
        {-1, 0, -1}, {1, 0, -1}, {-1, 0, 1}, {1, 0, 1},
        {0, -1, -1}, {0, 1, -1}, {0, -1, 1}, {0, 1, 1},
        {-2, 0, 0}, {2, 0, 0}, {0, -2, 0}, {0, 2, 0}, {0, 0, -2}, {0, 0, 2},
        {-3, 0, 0}, {3, 0, 0}, {0, -3, 0}, {0, 3, 0}, {0, 0, -3}, {0, 0, 3}
    };
    for (int n = 0; n < PATHN; ++n) {
        for (int s = 0; s < DIMS; ++s) {
            part->path[n][s] = path[n][s];
        }
    }
    const int base = 6; /* base directions in searching path */
    part->pathSep[1] = base; /* end index for layer 1 */
    part->pathSep[2] = part->pathSep[1] + 18; /* end index for layer 2 */
    part->pathSep[3] = part->pathSep[2] + base; /* end index for layer 3 */
    /* max search path for a spatial scheme */
    part->pathSep[0] = part->pathSep[part->gl];
    return;
}

// Assembly:
subq $0x28, %rsp
xorps %xmm0, %xmm0
leaq -0x30(%rsp), %rax
movaps %xmm0, (%rax)
movaps %xmm0, 0x10(%rax)
movaps %xmm0, 0x20(%rax)
movaps %xmm0, 0x30(%rax)
movaps %xmm0, 0x40(%rax)
orl $-0x1, 0xc(%rax)
movl $0x1, %ecx
movl %ecx, 0x18(%rax)
orl $-0x1, 0x28(%rax)
movl %ecx, 0x34(%rax)
orl $-0x1, 0x44(%rax)
movl %ecx, 0x50(%rax)
movq 0x3c0(%rdi), %rcx
xorl %edx, %edx
cmpq $0x7, %rdx
je 0xd852
xorl %esi, %esi
cmpq $0x3, %rsi
je 0xd845
movl (%rax,%rsi,4), %r8d
movl %r8d, (%rcx,%rsi,4)
incq %rsi
jmp 0xd832
incq %rdx
addq $0xc, %rcx
addq $0xc, %rax
jmp 0xd82a
movq 0x3b8(%rdi), %rax
leaq 0xac(%rdi), %rcx
leaq 0x13c(%rdi), %rdx
movabsq $0x1, %rsi
xorl %r8d, %r8d
cmpq $0x3, %r8
je 0xd948
cmpl $0x4, (%rax,%rsi,4)
movl 0x40(%rdi,%r8,4), %r9d
jne 0xd89b
movl %r9d, 0x90(%rdi,%r8,8)
movl 0x34(%rdi,%r8,4), %r10d
subl %r9d, %r10d
jmp 0xd8b2
leal 0x1(%r9), %r10d
movl %r10d, 0x90(%rdi,%r8,8)
notl %r9d
addl 0x34(%rdi,%r8,4), %r9d
movl %r9d, %r10d
movl %r10d, 0x94(%rdi,%r8,8)
xorl %r9d, %r9d
cmpq $0x90, %r9
je 0xd8e2
movl 0x40(%rdi,%r8,4), %r10d
movl %r10d, -0x4(%rcx,%r9)
movl 0x34(%rdi,%r8,4), %r11d
subl %r10d, %r11d
movl %r11d, (%rcx,%r9)
addq $0x18, %r9
jmp 0xd8bd
xorl %r9d, %r9d
cmpq $0x90, %r9
je 0xd903
andl $0x0, -0x4(%rdx,%r9)
movl 0x34(%rdi,%r8,4), %r10d
movl %r10d, (%rdx,%r9)
addq $0x18, %r9
jmp 0xd8e5
movl 0x40(%rdi,%r8,4), %r9d
movl %r9d, 0x1c8(%rdi,%r8,8)
movl 0x34(%rdi,%r8,4), %r10d
movl %r10d, %r11d
subl %r9d, %r11d
movl %r11d, 0x1cc(%rdi,%r8,8)
andl $0x0, 0x1e0(%rdi,%r8,8)
movl %r10d, 0x1e4(%rdi,%r8,8)
incq %r8
addq $0x2, %rsi
addq $0x8, %rcx
addq $0x8, %rdx
jmp 0xd874
leaq 0xac(%rdi), %rax
movabsq $0x1, %rcx
cmpq $0x7, %rcx
je 0xd970
movl -0x4(%rax), %edx
incl %edx
movl %edx, (%rax)
addq $0x2, %rcx
addq $0x38, %rax
jmp 0xd959
leaq 0xc4(%rdi), %rax
movabsq $0x2, %rcx
cmpq $0x8, %rcx
je 0xd998
movl (%rax), %edx
decl %edx
movl %edx, -0x4(%rax)
addq $0x2, %rcx
addq $0x38, %rax
jmp 0xd981
leaq 0x13c(%rdi), %rax
xorl %ecx, %ecx
cmpq $0x6, %rcx
je 0xd9b7
movl 0x40(%rdi,%rcx,2), %edx
movl %edx, (%rax)
addq $0x2, %rcx
addq $0x38, %rax
jmp 0xd9a1
movabsq $0x54, %rax
movabsq $0x1a, %rcx
cmpq $0x7e, %rax
je 0xd9e5
movl (%rdi,%rcx,2), %edx
subl 0xc(%rdi,%rcx,2), %edx
movl %edx, (%rdi,%rax,4)
addq $0xe, %rax
addq $0x2, %rcx
jmp 0xd9cb
movq 0x90(%rdi), %rcx
movq %rcx, %xmm0
leaq -0x80(%rsp), %rax
movq %rcx, (%rax)
movl 0x98(%rdi), %ecx
movl %ecx, 0x8(%rax)
movq 0x9c(%rdi), %rdx
movq %rdx, %xmm1
movq %rdx, 0xc(%rax)
movl 0xa4(%rdi), %esi
movl %esi, 0x14(%rax)
movl %ecx, 0x18(%rax)
movl %edx, 0x1c(%rax)
movd %esi, %xmm2
shufps $0xd4, %xmm1, %xmm2     # xmm2 = xmm2[0,1],xmm1[1,3]
movdqa %xmm0, %xmm1
shufps $0x24, %xmm2, %xmm1     # xmm1 = xmm1[0,1],xmm2[2,0]
movaps %xmm1, 0x20(%rax)
shufps $0x42, %xmm0, %xmm2     # xmm2 = xmm2[2,0],xmm0[0,1]
movaps %xmm2, 0x30(%rax)
movl %ecx, 0x40(%rax)
movl %edx, 0x44(%rax)
leaq 0x1f8(%rdi), %rcx
xorl %edx, %edx
cmpq $0x3, %rdx
je 0xda91
movq %rcx, %rsi
movq %rax, %r8
xorl %r9d, %r9d
cmpq $0x3, %r9
je 0xda84
xorl %r10d, %r10d
cmpq $0x2, %r10
je 0xda77
movl (%r8,%r10,4), %r11d
movl %r11d, (%rsi,%r10,4)
incq %r10
jmp 0xda64
incq %r9
addq $0x8, %r8
addq $0x8, %rsi
jmp 0xda5b
incq %rdx
addq $0x18, %rax
addq $0x18, %rcx
jmp 0xda4c
leaq 0x240(%rdi), %rax
leaq 0xdfb1(%rip), %rcx      # 0x1ba50
xorl %edx, %edx
cmpq $0x1e, %rdx
je 0xdac9
xorl %esi, %esi
cmpq $0x3, %rsi
je 0xdabc
movl (%rcx,%rsi,4), %r8d
movl %r8d, (%rax,%rsi,4)
incq %rsi
jmp 0xdaa9
incq %rdx
addq $0xc, %rcx
addq $0xc, %rax
jmp 0xdaa1
movabsq $0x1800000006, %rax     # imm = 0x1800000006
movq %rax, 0x3ac(%rdi)
movl $0x1e, 0x3b4(%rdi)
movslq 0x4c(%rdi), %rax
movl 0x3a8(%rdi,%rax,4), %eax
movl %eax, 0x3a8(%rdi)
addq $0x28, %rsp
retq
nop