Fix BSSN build config selection
This commit is contained in:
211
BSSN_BUILD_CONFIG_MIGRATION.md
Normal file
211
BSSN_BUILD_CONFIG_MIGRATION.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# BSSN Build Config Migration
|
||||
|
||||
This note records the build-configuration fix needed when replacing
|
||||
`AMSS_NCKU_Input.py` or `generate_macrodef.py` with a newer upstream version.
|
||||
|
||||
## Problem
|
||||
|
||||
`AMSS_NCKU_source/macrodef.h` is not the authoritative file used by normal
|
||||
runs. `AMSS_NCKU_Program.py` first generates macro files under
|
||||
`input_data.File_directory`, copies `AMSS_NCKU_source` to
|
||||
`<File_directory>/AMSS_NCKU_source_copy`, then copies the generated macro files
|
||||
into that copied source tree and compiles there.
|
||||
|
||||
Therefore, makefile logic must not depend only on the stale
|
||||
`AMSS_NCKU_source/macrodef.h`. The actual equation path must be passed to the
|
||||
copied build tree from the same generation step that creates `macrodef.h`.
|
||||
|
||||
The performance regression was caused by compiling/linking the
|
||||
`BSSN-EScalar` C wrapper into BSSN vacuum builds. For BSSN vacuum (`ABEtype=0`),
|
||||
the build must use:
|
||||
|
||||
```make
|
||||
BSSN_USE_TRANSFER_CACHE=1
|
||||
BSSN_USE_ESCALAR_C_KERNEL=0
|
||||
```
|
||||
|
||||
and must not link `bssn_escalar_rhs_c.o`.
|
||||
|
||||
## Required Migration Steps
|
||||
|
||||
### 1. Add an ABE type helper in `generate_macrodef.py`
|
||||
|
||||
Add a helper that maps `input_data.Equation_Class` to the numeric `ABEtype`.
|
||||
Use the same mapping as `macrodef.h`:
|
||||
|
||||
```python
|
||||
def get_abe_type():
|
||||
if ( input_data.Equation_Class == "BSSN" ):
|
||||
return 0
|
||||
elif ( input_data.Equation_Class == "BSSN-EScalar" ):
|
||||
return 1
|
||||
elif ( input_data.Equation_Class == "BSSN-EM" ):
|
||||
return 3
|
||||
elif ( input_data.Equation_Class == "Z4C" ):
|
||||
return 2
|
||||
else:
|
||||
raise ValueError("Equation_Class setting error!!!")
|
||||
```
|
||||
|
||||
Update `generate_macrodef_h()` to print `#define ABEtype {get_abe_type()}`
|
||||
instead of duplicating the if/elif mapping.
|
||||
|
||||
### 2. Generate a makefile fragment
|
||||
|
||||
In `generate_macrodef.py`, add:
|
||||
|
||||
```python
|
||||
def generate_build_config():
|
||||
file1 = open(os.path.join(input_data.File_directory, "AMSS_NCKU_build.mk"), "w")
|
||||
print("# Generated by generate_macrodef.py; do not edit manually.", file=file1)
|
||||
print(f"ABE_TYPE := {get_abe_type()}", file=file1)
|
||||
file1.close()
|
||||
```
|
||||
|
||||
This file is the build-time authority for the equation path.
|
||||
|
||||
### 3. Call and copy the generated build config
|
||||
|
||||
In `AMSS_NCKU_Program.py`, after generating `macrodef.h` and `macrodef.fh`, call:
|
||||
|
||||
```python
|
||||
generate_macrodef.generate_build_config()
|
||||
print(" AMSS-NCKU build config AMSS_NCKU_build.mk has been generated. ")
|
||||
```
|
||||
|
||||
When copying generated files into `AMSS_NCKU_source_copy`, also copy:
|
||||
|
||||
```python
|
||||
build_config_path = os.path.join(File_directory, "AMSS_NCKU_build.mk")
|
||||
shutil.copy2(build_config_path, AMSS_NCKU_source_copy)
|
||||
```
|
||||
|
||||
### 4. Make the source makefile consume the generated config
|
||||
|
||||
At the top of `AMSS_NCKU_source/makefile`, after `include makefile.inc`, add:
|
||||
|
||||
```make
|
||||
-include AMSS_NCKU_build.mk
|
||||
|
||||
ABE_TYPE ?= $(shell awk '/^[[:space:]]*\#define[[:space:]]+ABEtype/ {print $$3; exit}' macrodef.h 2>/dev/null)
|
||||
```
|
||||
|
||||
The generated `AMSS_NCKU_build.mk` is used during normal Python-driven builds.
|
||||
The fallback keeps manual source-tree builds usable.
|
||||
|
||||
### 5. Gate path-specific build options by `ABE_TYPE`
|
||||
|
||||
Use effective build switches:
|
||||
|
||||
```make
|
||||
ifeq ($(USE_TRANSFER_CACHE),auto)
|
||||
ifeq ($(ABE_TYPE),0)
|
||||
EFFECTIVE_USE_TRANSFER_CACHE = 1
|
||||
else
|
||||
EFFECTIVE_USE_TRANSFER_CACHE = 0
|
||||
endif
|
||||
else
|
||||
EFFECTIVE_USE_TRANSFER_CACHE = $(USE_TRANSFER_CACHE)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CXX_ESCALAR_KERNEL),1)
|
||||
ifeq ($(ABE_TYPE),1)
|
||||
EFFECTIVE_USE_CXX_ESCALAR_KERNEL = 1
|
||||
else
|
||||
EFFECTIVE_USE_CXX_ESCALAR_KERNEL = 0
|
||||
endif
|
||||
else
|
||||
EFFECTIVE_USE_CXX_ESCALAR_KERNEL = 0
|
||||
endif
|
||||
|
||||
TRANSFER_CACHE_FLAG = -DBSSN_USE_TRANSFER_CACHE=$(EFFECTIVE_USE_TRANSFER_CACHE)
|
||||
ESCALAR_KERNEL_FLAG = -DBSSN_USE_ESCALAR_C_KERNEL=$(EFFECTIVE_USE_CXX_ESCALAR_KERNEL)
|
||||
```
|
||||
|
||||
Only add `bssn_escalar_rhs_c.o` when the effective EScalar C kernel switch is
|
||||
enabled:
|
||||
|
||||
```make
|
||||
ifeq ($(EFFECTIVE_USE_CXX_ESCALAR_KERNEL),1)
|
||||
CFILES += bssn_escalar_rhs_c.o
|
||||
endif
|
||||
```
|
||||
|
||||
### 6. Use safe transfer-cache default
|
||||
|
||||
In `AMSS_NCKU_source/makefile.inc`, keep:
|
||||
|
||||
```make
|
||||
USE_TRANSFER_CACHE ?= auto
|
||||
```
|
||||
|
||||
With the effective switch logic above, this enables cached transfer for BSSN
|
||||
vacuum while keeping non-BSSN paths on the uncached path by default.
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Run these checks after migrating:
|
||||
|
||||
```bash
|
||||
python3 -c "import generate_macrodef; generate_macrodef.generate_build_config()"
|
||||
cat GW150914/AMSS_NCKU_build.mk
|
||||
```
|
||||
|
||||
For BSSN, the generated file should contain:
|
||||
|
||||
```make
|
||||
ABE_TYPE := 0
|
||||
```
|
||||
|
||||
Dry-run the copied or source makefile:
|
||||
|
||||
```bash
|
||||
make -n -B INTERP_LB_MODE=off ABE | grep -E 'BSSN_USE_TRANSFER_CACHE|BSSN_USE_ESCALAR_C_KERNEL|bssn_escalar_rhs_c'
|
||||
```
|
||||
|
||||
Expected BSSN result:
|
||||
|
||||
```text
|
||||
-DBSSN_USE_TRANSFER_CACHE=1 -DBSSN_USE_ESCALAR_C_KERNEL=0
|
||||
```
|
||||
|
||||
and no `bssn_escalar_rhs_c.o` in the final link command.
|
||||
|
||||
Run the full workflow:
|
||||
|
||||
```bash
|
||||
python3 AMSS_NCKU_Program.py
|
||||
```
|
||||
|
||||
For the 10-step BSSN test, compare coordinate output:
|
||||
|
||||
```bash
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
old = Path('../GW150914-06457/AMSS_NCKU_output/bssn_BH.dat')
|
||||
new = Path('GW150914/AMSS_NCKU_output/bssn_BH.dat')
|
||||
|
||||
def rows(path):
|
||||
out = []
|
||||
for line in path.read_text().splitlines():
|
||||
if not line.strip() or line.lstrip().startswith('#'):
|
||||
continue
|
||||
out.append([float(x) for x in line.split()])
|
||||
return out
|
||||
|
||||
ro, rn = rows(old), rows(new)
|
||||
n = min(len(ro), len(rn))
|
||||
max_abs = 0.0
|
||||
for i in range(n):
|
||||
for a, b in zip(ro[i], rn[i]):
|
||||
max_abs = max(max_abs, abs(a - b))
|
||||
print(f"old_rows={len(ro)} new_rows={len(rn)} compared_rows={n}")
|
||||
print(f"max_abs_diff={max_abs:.17g}")
|
||||
PY
|
||||
```
|
||||
|
||||
For the validated migration, the first 10 rows matched exactly:
|
||||
|
||||
```text
|
||||
max_abs_diff=0
|
||||
```
|
||||
Reference in New Issue
Block a user