// File: /workspace/github_c_makefile_star2_O3/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
movaps %xmm0, -0x30(%rsp)
movaps %xmm0, -0x20(%rsp)
movaps %xmm0, -0x10(%rsp)
movaps %xmm0, (%rsp)
movaps %xmm0, 0x10(%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, -0x24(%rsp)
movl $0x1, %ecx
movl %ecx, -0x18(%rsp)
movl %eax, -0x8(%rsp)
movl %ecx, 0x4(%rsp)
movl %eax, 0x14(%rsp)
movl %ecx, 0x20(%rsp)
movq 0x3c0(%rdi), %rax
xorl %ecx, %ecx
movl -0x28(%rsp,%rcx), %edx
movl %edx, 0x8(%rax,%rcx)
movq -0x30(%rsp,%rcx), %rdx
movq %rdx, (%rax,%rcx)
addq $0xc, %rcx
cmpq $0x54, %rcx
jne 0xe182
movq 0x3b8(%rdi), %rax
leaq 0xac(%rdi), %rcx
leaq 0x13c(%rdi), %rdx
movl $0x1, %esi
xorl %r8d, %r8d
cmpl $0x4, (%rax,%rsi,4)
movl 0x40(%rdi,%r8,4), %r9d
jne 0xe1d7
movl %r9d, 0x90(%rdi,%r8,8)
movl 0x34(%rdi,%r8,4), %r10d
subl %r9d, %r10d
jmp 0xe1ee
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
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
cmpq $0x90, %r9
jne 0xe1f9
xorl %r9d, %r9d
movl $0x0, -0x4(%rdx,%r9)
movl 0x34(%rdi,%r8,4), %r10d
movl %r10d, (%rdx,%r9)
addq $0x18, %r9
cmpq $0x90, %r9
jne 0xe21f
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)
movl $0x0, 0x1e0(%rdi,%r8,8)
movl %r10d, 0x1e4(%rdi,%r8,8)
incq %r8
addq $0x2, %rsi
addq $0x8, %rcx
addq $0x8, %rdx
cmpq $0x3, %r8
jne 0xe1ba
leaq 0xac(%rdi), %rax
xorl %ecx, %ecx
movl -0x4(%rax), %edx
incl %edx
movl %edx, (%rax)
incq %rcx
addq $0x38, %rax
cmpq $0x3, %rcx
jne 0xe294
leaq 0xc4(%rdi), %rax
xorl %ecx, %ecx
movl (%rax), %edx
decl %edx
movl %edx, -0x4(%rax)
incq %rcx
addq $0x38, %rax
cmpq $0x3, %rcx
jne 0xe2b1
leaq 0x13c(%rdi), %rax
xorl %ecx, %ecx
movl 0x40(%rdi,%rcx,4), %edx
movl %edx, (%rax)
incq %rcx
addq $0x38, %rax
cmpq $0x3, %rcx
jne 0xe2ce
leaq 0x150(%rdi), %rax
xorl %ecx, %ecx
movl 0x34(%rdi,%rcx,4), %edx
subl 0x40(%rdi,%rcx,4), %edx
movl %edx, (%rax)
incq %rcx
addq $0x38, %rax
cmpq $0x3, %rcx
jne 0xe2ea
movq 0x90(%rdi), %rax
movq %rax, %xmm0
movq %rax, -0x80(%rsp)
movl 0x98(%rdi), %eax
movl %eax, -0x78(%rsp)
movq 0x9c(%rdi), %rcx
movq %rcx, %xmm1
movq %rcx, -0x74(%rsp)
movl 0xa4(%rdi), %edx
movl %edx, -0x6c(%rsp)
movl %eax, -0x68(%rsp)
movl %ecx, -0x64(%rsp)
movd %edx, %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, -0x60(%rsp)
shufps $0x42, %xmm0, %xmm2     # xmm2 = xmm2[2,0],xmm0[0,1]
movaps %xmm2, -0x50(%rsp)
movl %eax, -0x40(%rsp)
movl %ecx, -0x3c(%rsp)
leaq 0x1f8(%rdi), %rax
xorl %ecx, %ecx
movq -0x70(%rsp,%rcx), %rdx
movq %rdx, 0x10(%rax,%rcx)
movups -0x80(%rsp,%rcx), %xmm0
movups %xmm0, (%rax,%rcx)
addq $0x18, %rcx
cmpq $0x48, %rcx
jne 0xe36e
leaq 0x240(%rdi), %rax
xorl %ecx, %ecx
leaq 0xe7d5(%rip), %rdx      # 0x1cb70
movl 0x8(%rcx,%rdx), %esi
movl %esi, 0x8(%rax,%rcx)
movq (%rcx,%rdx), %rsi
movq %rsi, (%rax,%rcx)
addq $0xc, %rcx
cmpq $0x168, %rcx            # imm = 0x168
jne 0xe39b
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
nopl (%rax)