Skip to content

Commit b569dae

Browse files
authored
Update atat_module.py
1 parent 44a1b6e commit b569dae

1 file changed

Lines changed: 112 additions & 15 deletions

File tree

atat_module.py

Lines changed: 112 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4941,7 +4941,7 @@ def render_extended_optimization_analysis_tab():
49414941

49424942

49434943
def generate_atat_monitor_script(results, use_atom_count=False, parallel_runs=1, pair_cutoff=1.1, triplet_cutoff=None,
4944-
quadruplet_cutoff=None,max_param=1.0):
4944+
quadruplet_cutoff=None,max_param=1.0,time_limit_minutes=None):
49454945
if use_atom_count:
49464946
mcsqs_base_cmd = f"mcsqs -n {results['total_atoms']}"
49474947
else:
@@ -4956,7 +4956,11 @@ def generate_atat_monitor_script(results, use_atom_count=False, parallel_runs=1,
49564956
if parallel_runs > 1:
49574957
mcsqs_commands = []
49584958
for i in range(1, parallel_runs + 1):
4959-
mcsqs_commands.append(f"{mcsqs_base_cmd} -ip={i} &")
4959+
if time_limit_minutes:
4960+
mcsqs_commands.append(
4961+
f"timeout {time_limit_minutes * 60}s {mcsqs_base_cmd} -ip={i} > mcsqs{i}.log 2>&1 || true &")
4962+
else:
4963+
mcsqs_commands.append(f"{mcsqs_base_cmd} -ip={i} > mcsqs{i}.log 2>&1 &")
49604964
mcsqs_execution = "\n".join(mcsqs_commands)
49614965
log_file = "mcsqs1.log"
49624966
mcsqs_display_cmd = f"{mcsqs_base_cmd} -ip=1 & {mcsqs_base_cmd} -ip=2 & ... (parallel execution)"
@@ -5049,7 +5053,13 @@ def generate_atat_monitor_script(results, use_atom_count=False, parallel_runs=1,
50495053
monitor_call = "start_parallel_monitoring_process \"$PROGRESS_FILE\" &"
50505054

50515055
else:
5052-
mcsqs_execution = f"{mcsqs_base_cmd} > \"$LOG_FILE\" 2>&1 &"
5056+
if time_limit_minutes:
5057+
mcsqs_execution = f"timeout {time_limit_minutes * 60}s {mcsqs_base_cmd} > \"$LOG_FILE\" 2>&1 || true &"
5058+
else:
5059+
if time_limit_minutes:
5060+
mcsqs_execution = f"timeout {time_limit_minutes * 60}s {mcsqs_base_cmd} > \"$LOG_FILE\" 2>&1 || true &"
5061+
else:
5062+
mcsqs_execution = f"{mcsqs_base_cmd} > \"$LOG_FILE\" 2>&1 &"
50535063
log_file = "mcsqs.log"
50545064
mcsqs_display_cmd = mcsqs_base_cmd
50555065
progress_file = "mcsqs_progress.csv"
@@ -5116,6 +5126,8 @@ def generate_atat_monitor_script(results, use_atom_count=False, parallel_runs=1,
51165126
LOG_FILE="{log_file}"
51175127
PROGRESS_FILE="{progress_file}"
51185128
DEFAULT_MCSQS_ARGS="{mcsqs_base_cmd.split('mcsqs ')[1]}"
5129+
{"TIME_LIMIT_MINUTES=" + str(time_limit_minutes) if time_limit_minutes else "TIME_LIMIT_MINUTES=0"}
5130+
TIME_LIMIT_SECONDS=$((TIME_LIMIT_MINUTES * 60))
51195131
51205132
# --- Auto-generate ATAT Input Files ---
51215133
create_input_files() {{
@@ -5283,6 +5295,7 @@ def write_poscar(lattice, atoms, filename, comment):
52835295
echo "🧹 Stopping MCSQS processes..."
52845296
if [ -n "$MCSQS_PID" ]; then kill "$MCSQS_PID" 2>/dev/null; fi
52855297
if [ -n "$MONITOR_PID" ]; then kill "$MONITOR_PID" 2>/dev/null; fi
5298+
if [ -n "$TIMER_PID" ]; then kill "$TIMER_PID" 2>/dev/null; fi
52865299
pkill -9 -f "mcsqs" 2>/dev/null || true
52875300
sleep 2
52885301
@@ -5363,52 +5376,116 @@ def write_poscar(lattice, atoms, filename, comment):
53635376
echo " - Supercell: {results['supercell_size']} ({results['total_atoms']} atoms)"
53645377
echo " - Parallel runs: {parallel_runs}"
53655378
echo " - Command: {mcsqs_display_cmd}"
5379+
{"echo \" - Time limit: $TIME_LIMIT_MINUTES minutes\"" if time_limit_minutes else "echo \" - Time limit: None (manual stop)\""}
53665380
echo " - Log file: $LOG_FILE"
53675381
echo " - Progress file: $PROGRESS_FILE"
53685382
echo "================================================"
53695383
53705384
check_prerequisites
53715385
53725386
rm -f "$LOG_FILE" "$PROGRESS_FILE" mcsqs*.log
5373-
53745387
echo ""
53755388
echo "Starting ATAT MCSQS optimization and progress monitor..."
53765389
53775390
{mcsqs_execution}
53785391
MCSQS_PID=$!
53795392
5393+
5394+
53805395
{monitor_call}
53815396
MONITOR_PID=$!
53825397
53835398
echo "✅ MCSQS started"
53845399
echo "✅ Monitor started (PID: $MONITOR_PID)"
53855400
echo ""
53865401
echo "Real-time progress logged to: $PROGRESS_FILE"
5387-
echo "Press Ctrl+C to stop optimization and monitoring."
5402+
if [ $TIME_LIMIT_MINUTES -gt 0 ]; then
5403+
echo "⏱️ Will auto-stop after $TIME_LIMIT_MINUTES minutes"
5404+
echo "Press Ctrl+C to stop earlier and auto-convert to POSCAR."
5405+
else
5406+
echo "Press Ctrl+C to stop optimization and auto-convert to POSCAR."
5407+
fi
53885408
echo "================================================"
53895409
53905410
{"wait" if parallel_runs > 1 else "wait $MCSQS_PID"}
53915411
MCSQS_EXIT_CODE=$?
53925412
53935413
echo ""
5394-
echo "MCSQS process finished with exit code: $MCSQS_EXIT_CODE."
5414+
if [ $MCSQS_EXIT_CODE -eq 124 ]; then
5415+
echo "⏱️ Time limit reached ($TIME_LIMIT_MINUTES minutes). MCSQS stopped automatically."
5416+
else
5417+
echo "MCSQS process finished with exit code: $MCSQS_EXIT_CODE."
5418+
fi
53955419
53965420
echo "Allowing monitor to capture final data..."
5397-
sleep 65
5421+
sleep 5
53985422
53995423
kill $MONITOR_PID 2>/dev/null
54005424
wait $MONITOR_PID 2>/dev/null
54015425
5426+
echo ""
5427+
echo "=========================================="
5428+
echo "🔄 Converting bestsqs files to POSCAR..."
5429+
echo "=========================================="
5430+
5431+
found_files=0
5432+
best_run=""
5433+
best_objective=""
5434+
5435+
if [ -f "$PROGRESS_FILE" ]; then
5436+
last_line=$(tail -1 "$PROGRESS_FILE")
5437+
{"best_objective=$(echo \"$last_line\" | cut -d',' -f$((3 + 3 * " + str(parallel_runs) + ")))" if parallel_runs > 1 else "best_objective=$(echo \"$last_line\" | cut -d',' -f4)"}
5438+
{"best_run=$(echo \"$last_line\" | cut -d',' -f$((4 + 3 * " + str(parallel_runs) + ")) | sed 's/Run//')" if parallel_runs > 1 else "best_run=\"1\""}
5439+
fi
5440+
5441+
for outfile in bestsqs*.out; do
5442+
if [ -f "$outfile" ]; then
5443+
found_files=1
5444+
basename="${{outfile%.out}}"
5445+
poscar_file="${{basename}}_POSCAR"
5446+
5447+
if convert_bestsqs_to_poscar "$outfile" "$poscar_file"; then
5448+
echo " ✅ $outfile → $poscar_file"
5449+
else
5450+
echo " ❌ Failed to convert $outfile"
5451+
fi
5452+
fi
5453+
done
5454+
5455+
if [ $found_files -eq 0 ]; then
5456+
echo " ⚠️ No bestsqs*.out files found"
5457+
else
5458+
if [ -n "$best_run" ] && [ -n "$best_objective" ]; then
5459+
if [ {parallel_runs} -gt 1 ]; then
5460+
best_poscar="bestsqs${{best_run}}_POSCAR"
5461+
else
5462+
best_poscar="bestsqs_POSCAR"
5463+
fi
5464+
5465+
if [ -f "$best_poscar" ]; then
5466+
cp "$best_poscar" "POSCAR_best_overall"
5467+
echo ""
5468+
echo "🏆 Best structure (objective: $best_objective) saved as POSCAR_best_overall"
5469+
if [ {parallel_runs} -gt 1 ]; then
5470+
echo " Source: Run $best_run (bestsqs${{best_run}}.out)"
5471+
else
5472+
echo " Source: bestsqs.out"
5473+
fi
5474+
else
5475+
echo ""
5476+
echo "⚠️ Could not find best POSCAR file: $best_poscar"
5477+
fi
5478+
else
5479+
echo ""
5480+
echo "⚠️ Could not determine best structure (no progress data found)"
5481+
fi
5482+
fi
5483+
54025484
echo ""
54035485
echo "================================================"
54045486
echo " Optimization Complete"
54055487
echo "================================================"
5406-
echo "Results:"
5407-
echo " - MCSQS log: $LOG_FILE"
5408-
echo " - Progress data: $PROGRESS_FILE"
5409-
echo " - Best structure: bestsqs.out (if generated)"
5410-
echo " - Correlation data: bestcorr.out (if generated)"
5411-
echo ""
5488+
54125489
54135490
if [ -f "$PROGRESS_FILE" ]; then
54145491
echo "Progress Summary:"
@@ -5431,7 +5508,6 @@ def render_monitor_script_section(results):
54315508
- ✅ **Executes mcsqs** with real-time monitoring
54325509
- ✅ **Generates CSV progress** data every minute
54335510
- ✅ **Supports parallel execution** for faster results
5434-
- ✅ **Creates POSCAR** automatically from bestsqs.out
54355511
""")
54365512

54375513
# Configuration options
@@ -5467,6 +5543,26 @@ def render_monitor_script_section(results):
54675543
else:
54685544
parallel_runs = 1
54695545

5546+
st.write("**Time Limit:**")
5547+
enable_time_limit = st.checkbox(
5548+
"Set automatic time limit",
5549+
value=False,
5550+
help="Automatically stop mcsqs after specified time",
5551+
key="monitor_enable_time_limit"
5552+
)
5553+
5554+
if enable_time_limit:
5555+
time_limit_minutes = st.number_input(
5556+
"Time limit (minutes):",
5557+
min_value=1,
5558+
max_value=10080,
5559+
value=30,
5560+
step=5,
5561+
key="monitor_time_limit"
5562+
)
5563+
else:
5564+
time_limit_minutes = None
5565+
54705566
with col_opt3:
54715567
st.write("**Cluster Settings:**")
54725568
pair_cutoff = results.get('pair_cutoff', 1.1)
@@ -5501,7 +5597,8 @@ def render_monitor_script_section(results):
55015597
pair_cutoff=pair_cutoff,
55025598
triplet_cutoff=triplet_cutoff,
55035599
quadruplet_cutoff=quadruplet_cutoff,
5504-
max_param=results.get('max_param', 1.0)
5600+
max_param=results.get('max_param', 1.0),
5601+
time_limit_minutes=time_limit_minutes
55055602
)
55065603

55075604
st.download_button(

0 commit comments

Comments
 (0)