diff --git a/examples/000_build_executable/000_build_executable.py b/examples/000_build_executable/000_build_executable.py deleted file mode 100644 index d160494..0000000 --- a/examples/000_build_executable/000_build_executable.py +++ /dev/null @@ -1,4 +0,0 @@ -import xboinc as xb - -source_files = xb.generate_executable_source() - diff --git a/examples/000_build_executable/001mac_compile_executable.sh b/examples/000_build_executable/001mac_compile_executable.sh deleted file mode 100644 index 3899404..0000000 --- a/examples/000_build_executable/001mac_compile_executable.sh +++ /dev/null @@ -1 +0,0 @@ -clang main.c -o xboinc_executable diff --git a/examples/000_build_executable/001msys2_compile_executable.sh b/examples/000_build_executable/001msys2_compile_executable.sh deleted file mode 100755 index 6fe9c0f..0000000 --- a/examples/000_build_executable/001msys2_compile_executable.sh +++ /dev/null @@ -1 +0,0 @@ -gcc main.c -o xboinc_executable -lm diff --git a/examples/001_simple_line/001_build_input.py b/examples/001_simple_line/001_build_input.py deleted file mode 100644 index 28d3d15..0000000 --- a/examples/001_simple_line/001_build_input.py +++ /dev/null @@ -1,13 +0,0 @@ -import xtrack as xt -import xpart as xp -import xboinc as xb - -# Simulation input -num_turns = 10 -line = xt.Line(elements=[ - xt.Drift(length=1.0), xt.Multipole(knl=[1e-6]), xt.Drift(length=1.0)]) -particles = xp.Particles(mass0=xp.PROTON_MASS_EV, p0c=7e12, x=[1e-3,2e-3,3e-3]) - -# Assemble data structure -xb.build_input_file(line=line, particles=particles, num_turns=num_turns, - name='xboinc_input.bin') \ No newline at end of file diff --git a/examples/001_simple_line/002_run_executable.sh b/examples/001_simple_line/002_run_executable.sh deleted file mode 100755 index ad355a8..0000000 --- a/examples/001_simple_line/002_run_executable.sh +++ /dev/null @@ -1 +0,0 @@ -../000_build_executable/xboinc_executable diff --git a/examples/001_simple_line/003_read_output.py b/examples/001_simple_line/003_read_output.py deleted file mode 100644 index 2529e77..0000000 --- a/examples/001_simple_line/003_read_output.py +++ /dev/null @@ -1,16 +0,0 @@ -import numpy as np - -import xboinc as xb - -# Read output -filename = 'sim_state_out.bin' -sim_state = xb.read_output_file(filename) - -# Look at particles state -particles = sim_state.particles - -assert np.all(particles.s == 20) -assert np.all(particles.at_turn == 10) -assert sim_state.i_turn == 10 - -print('All checks passed!') \ No newline at end of file diff --git a/examples/002_lhc/001_build_input.py b/examples/002_lhc/001_build_input.py deleted file mode 100644 index 6e0f5cf..0000000 --- a/examples/002_lhc/001_build_input.py +++ /dev/null @@ -1,25 +0,0 @@ -import json -import numpy as np - -import xtrack as xt -import xpart as xp -import xboinc as xb - -filename = xt._pkg_root.parent.joinpath( - 'test_data/lhc_with_bb/line_and_particle.json') - -with open(filename, 'r') as fid: - input_data = json.load(fid) - -# We add some particles -input_data['particle']['x'] += np.linspace(0, 1e-3, 10) - -# Simulation input -num_turns = 1000 -line = xt.Line.from_dict(input_data['line']) -particles = xp.Particles.from_dict(input_data['particle']) - -# Assemble data structure -xb.build_input_file( - line=line, particles=particles, num_turns=num_turns, checkpoint_every=100, - name='xboinc_input.bin') diff --git a/examples/002_lhc/002_run_executable.sh b/examples/002_lhc/002_run_executable.sh deleted file mode 100755 index ad355a8..0000000 --- a/examples/002_lhc/002_run_executable.sh +++ /dev/null @@ -1 +0,0 @@ -../000_build_executable/xboinc_executable diff --git a/examples/002_lhc/003_read_output.py b/examples/002_lhc/003_read_output.py deleted file mode 100644 index 7af5833..0000000 --- a/examples/002_lhc/003_read_output.py +++ /dev/null @@ -1,16 +0,0 @@ -import numpy as np - -import xboinc as xb - -# Read output -filename = 'sim_state_out.bin' -sim_state = xb.read_output_file(filename) - -# Look at particles state -particles = sim_state.particles - -assert np.allclose(particles.s, 0, rtol=1e-6, atol=0) -assert np.all(particles.at_turn == 1000) -assert sim_state.i_turn == 1000 - -print('All checks passed!') diff --git a/examples/002_lhc/mac_input/xboinc_input.bin b/examples/002_lhc/mac_input/xboinc_input.bin deleted file mode 100644 index 3cf0dec..0000000 Binary files a/examples/002_lhc/mac_input/xboinc_input.bin and /dev/null differ diff --git a/examples/002_lhc/windows_output/sim_state_out.bin b/examples/002_lhc/windows_output/sim_state_out.bin deleted file mode 100644 index df90d81..0000000 Binary files a/examples/002_lhc/windows_output/sim_state_out.bin and /dev/null differ diff --git a/examples/003_boinc/000_build_executable.py b/examples/003_boinc/000_build_executable.py deleted file mode 100644 index d160494..0000000 --- a/examples/003_boinc/000_build_executable.py +++ /dev/null @@ -1,4 +0,0 @@ -import xboinc as xb - -source_files = xb.generate_executable_source() - diff --git a/examples/003_boinc/002_read_output.py b/examples/003_boinc/002_read_output.py deleted file mode 100644 index 311edc5..0000000 --- a/examples/003_boinc/002_read_output.py +++ /dev/null @@ -1,16 +0,0 @@ -import numpy as np - -import xboinc as xb - -# Read output -filename = 'out' -sim_state = xb.read_output_file(filename) - -# Look at particles state -particles = sim_state.particles - -assert np.allclose(particles.s, 2.665888e+04*1000, rtol=1e-6, atol=0) -assert np.all(particles.at_turn == 1000) -assert sim_state.i_turn == 1000 - -print('All checks passed!') diff --git a/examples/003_boinc/Makefile b/examples/003_boinc/Makefile deleted file mode 100644 index 1501f17..0000000 --- a/examples/003_boinc/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# This should work on Linux. Modify as needed for other platforms. - -BOINC_SOURCE_API_DIR = $(BOINC_DIR)/api -BOINC_SOURCE_LIB_DIR = $(BOINC_DIR)/lib -BOINC_SOURCE_ZIP_DIR = $(BOINC_DIR)/zip -FREETYPE_DIR = /usr/include/freetype2 - -BOINC_API_DIR = $(BOINC_SOURCE_API_DIR) -BOINC_LIB_DIR = $(BOINC_SOURCE_LIB_DIR) -BOINC_ZIP_DIR = $(BOINC_SOURCE_ZIP_DIR) - -#MAKEFILE_LDFLAGS = -lpthread libstdc++.a -MAKEFILE_LDFLAGS = -lpthread libstdc++.a -static -MAKEFILE_STDLIB = libstdc++.a - -CXXFLAGS += -g \ - -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common \ - -DAPP_GRAPHICS \ - -I$(BOINC_DIR) \ - -I$(BOINC_SOURCE_API_DIR) \ - -I$(BOINC_SOURCE_LIB_DIR) \ - -I$(BOINC_SOURCE_ZIP_DIR) \ - -I$(FREETYPE_DIR) \ - -L$(BOINC_API_DIR) \ - -L$(BOINC_LIB_DIR) \ - -L/usr/X11R6/lib \ - -L. - -# to get the graphics app to compile you may need to install some packages -# e.g. ftgl-devel.x86_64 -# -# You may have to change the paths for your system. - -LIBGLUT = -lglut -LIBGLU = -lGLU -LIBGL= -lGL -LIBUI = -lX11 -lXmu -LIBFTGL = -lftgl -LIBJPEG = -ljpeg - -ifdef BUILD_WITH_VCPKG - BUILD_DIR = $(BOINC_DIR)/3rdParty/linux - VCPKG_DIR ?= $(BUILD_DIR)/vcpkg/installed/x64-linux - - CXXFLAGS += \ - -I$(VCPKG_DIR)/include \ - -L$(VCPKG_DIR)/lib - - LIBUI = -lX11 -lXmu -lXrandr -lXxf86vm -lXi - LIBFTGL = -lftgl -lfreetype -lpng -lbz2 -lbrotlidec-static -lbrotlienc-static -lbrotlicommon-static -lz -endif - -ifdef BUILD_WITH_MINGW - LIBGLUT = -lfreeglut_static - LIBGLU = -lglu32 - LIBGL= -lopengl32 - LIBUI = -lgdi32 -lwinmm - LIBFTGL = -lftgl -lfreetype -lpng -lbz2 -lbrotlidec-static -lbrotlienc-static -lbrotlicommon-static -lz -endif - -PROGS = xtrack -# make this optional so compile doesn't break on systems without OpenGL - -$(info All PROGS=$(PROGS)) - -all: $(PROGS) - -libstdc++.a: - ln -s `$(CXX) -print-file-name=libstdc++.a` - -ttfont.cpp: - ln -s ../../api/ttfont.cpp . - -clean: distclean - -distclean: - /bin/rm -f $(PROGS) $(addsuffix .exe, $(PROGS)) *.o libstdc++.a ttfont.cpp - -install: xtrack - -# specify library paths explicitly (rather than -l) -# because otherwise you might get a version in /usr/lib etc. - -xtrack: xtrack.o $(MAKEFILE_STDLIB) $(BOINC_API_DIR)/libboinc_api.a $(BOINC_LIB_DIR)/libboinc.a - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o xtrack xtrack.o \ - -o xboinc_executable -lm \ - -lboinc_api -lboinc $(MAKEFILE_LDFLAGS) \ - $(STDCPPTC) - diff --git a/examples/003_boinc/cleanall.sh b/examples/003_boinc/cleanall.sh deleted file mode 100644 index a0accb9..0000000 --- a/examples/003_boinc/cleanall.sh +++ /dev/null @@ -1,11 +0,0 @@ -rm boinc_finish_called -rm checkpoint.bin -rm libstdc++.a -rm main.c -rm out -rm sim_config.h -rm stderr.txt -rm xboinc_executable.exe -rm xboinc_input.bin -rm xtrack.o -rm xtrack_tracker.h diff --git a/examples/003_boinc/client_state_save.xml b/examples/003_boinc/client_state_save.xml deleted file mode 100644 index fa0c036..0000000 --- a/examples/003_boinc/client_state_save.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - 1e9 - 2e9 - 2e9 - 1e11 - 1e11 - - - http://test.test - test_project - - - - test_app - test_app - - - - xboinc_executable - - 1 - - - input.bin - 1 - - - output.bin - - 1e7 - - - - - - - test_app - 6.3.0 - - xboinc_executable - - - - - - test_wu - test_app - - input.bin - xboinc_input.bin - - - - - test_result - test_wu - 2 - 2e9 - - output.bin - out - - - -3 - - diff --git a/examples/003_boinc/xtrack.cpp b/examples/003_boinc/xtrack.cpp deleted file mode 100644 index 8229ed7..0000000 --- a/examples/003_boinc/xtrack.cpp +++ /dev/null @@ -1,298 +0,0 @@ -// This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2008 University of California -// -// BOINC is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// BOINC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with BOINC. If not, see . - -// command line options -// --cpu_time N: use about N CPU seconds after copying files -// --critical_section: run most of the time in a critical section -// --early_exit: exit(10) after 30 chars -// --early_crash: crash after 30 chars -// --run_slow: sleep 1 second after each character -// --trickle_up: sent a trickle-up message -// --trickle_down: receive a trickle-up message -// --network_usage: tell the client we used some network - -#include -#ifndef NULL - #define NULL 0 -#endif -#include - -#include "xtrack_tracker.h" -#include "sim_config.h" - -#ifdef _WIN32 -#include "boinc_win.h" -#else -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "str_util.h" -#include "util.h" -#include "filesys.h" -#include "boinc_api.h" -#include "mfile.h" -#include "graphics2.h" -#include "xtrack.h" - -#include - -#ifdef APP_GRAPHICS -UC_SHMEM* shmem; -#endif - -using std::string; - -#define CHECKPOINT_FILE "checkpoint.bin" -#define INPUT_FILENAME "xboinc_input.bin" -#define OUTPUT_FILENAME "out" - -bool run_slow = false; -bool early_exit = false; -bool early_crash = false; -bool early_sleep = false; -bool trickle_up = false; -bool trickle_down = false; -bool critical_section = false; // run most of the time in a critical section -bool report_fraction_done = true; -bool network_usage = false; -double cpu_time = 20, comp_result; - -int8_t* file_to_buffer(FILE* sim_fid, int8_t* buf_in){ - - //FILE *sim_fid; - int8_t *buf; - - // Get buffer - //sim_fid = fopen(filename, "rb"); - if (!sim_fid){ - return NULL; - } - fseek(sim_fid, 0L, SEEK_END); - unsigned long filesize = ftell(sim_fid); - fseek(sim_fid, 0L, SEEK_SET); - if (buf_in){ - printf("Reusing buffer\n"); - buf = buf_in; - } - else{ - buf = (int8_t*)malloc(filesize*sizeof(int8_t)); - } - fread(buf, sizeof(int8_t), filesize, sim_fid); - fclose(sim_fid); - - return (buf); -} - -int do_checkpoint(SimConfig sim_config, SimStateData sim_state) { - - int retval; - FILE *chkp_fid; - char resolved_name[512], buf[256]; - - boinc_resolve_filename(CHECKPOINT_FILE, resolved_name, sizeof(resolved_name)); - - chkp_fid = boinc_fopen(resolved_name, "wb"); - if (!chkp_fid) { - fprintf(stderr, - "%s Couldn't find checkpoint file, name %s.\n", - boinc_msg_prefix(buf, sizeof(buf)), resolved_name); - return 1; - } - - printf("Checkpointing turn %d!\n", (int) SimStateData_get_i_turn(sim_state)); - - fwrite(SimConfig_getp_sim_state(sim_config), sizeof(int8_t), SimConfig_get_sim_state_size(sim_config), chkp_fid); - - fclose(chkp_fid); - - return 0; -} - - -int main(int argc, char **argv) { - int i; - int c, nchars = 0, retval, n; - double fsize, fd; - char input_path[512], output_path[512], chkpt_path[512], buf[256]; - FILE* out; - FILE* state, *infile; - - for (i=0; i 0 && SimStateData_get_i_turn(sim_state) % checkpoint_every == 0) ){ - retval = do_checkpoint(sim_config, sim_state); - if (retval) { - fprintf(stderr, "%s APP: xtrack checkpoint failed %d\n", boinc_msg_prefix(buf, sizeof(buf))); - exit(retval); - } - boinc_checkpoint_completed(); - } - - if (report_fraction_done) { - fd = (int)SimStateData_get_i_turn(sim_state) / (int)num_turns; - if (cpu_time) fd /= 2; - boinc_fraction_done(fd); - } - - } - - // Quick check - //for (int ii=0; ii("example_app"), - const_cast("sample trickle message") - ); - } - - if (trickle_down) { - boinc_sleep(10); - retval = boinc_receive_trickle_down(buf, sizeof(buf)); - if (!retval) { - fprintf(stderr, "Got trickle-down message: %s\n", buf); - } - } - - - boinc_fraction_done(1); - - boinc_finish(0); -} - diff --git a/examples/003_boinc/xtrack.h b/examples/003_boinc/xtrack.h deleted file mode 100644 index 6aff662..0000000 --- a/examples/003_boinc/xtrack.h +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2008 University of California -// -// BOINC is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// BOINC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with BOINC. If not, see . - -#include "boinc_api.h" - -struct UC_SHMEM { - double update_time; - double fraction_done; - double cpu_time; - BOINC_STATUS status; - int countdown; - // graphics app sets this to 5 repeatedly, - // main program decrements it once/sec. - // If it's zero, don't bother updating shmem -}; - -#ifdef _WIN32 - -extern "C" { - -__declspec( dllimport ) char* xtrack_dll_version(); - -}; - -#endif - diff --git a/examples/004_submissions/001_sub_noloop.py b/examples/004_submissions/001_sub_noloop.py deleted file mode 100644 index cb8dceb..0000000 --- a/examples/004_submissions/001_sub_noloop.py +++ /dev/null @@ -1,51 +0,0 @@ -import json -import glob -import tarfile -import itertools - -import numpy as np - -import xtrack as xt -import xpart as xp -import xboinc as xb - -eos = '' -user = 'ddicroce' # this should be read from a config json in the eos written by the boinc server -name = 'test_noloop' - -filename = xt._pkg_root.parent.joinpath( - 'test_data/lhc_with_bb/line_and_particle.json') - -with open(filename, 'r') as fid: - input_data = json.load(fid) - - -# loop or anything that user wishes -nparticles = 6000 # approximate number of particles to be generated -ndims = 2 -dim_names = ['x', 'y'] -particles_per_dim = int(round(nparticles ** (1.0/ndims))) -coords = list(itertools.product(*[np.linspace(0, 1e-3, particles_per_dim) for i in range(ndims)])) - -for dim_name in dim_names: - input_data['particle'][dim_name] = [] - -for coord in coords: - for i, dim_name in enumerate(dim_names): - input_data['particle'][dim_name].append(coord[i]) - -for dim_name in dim_names: - input_data['particle'][dim_name] = np.array(input_data['particle'][dim_name])[:nparticles] - -print('# particles:', len(input_data['particle'][dim_names[-1]]), ' | ', particles_per_dim, ' per dimension') # real number of particles - -# Simulation input -num_turns = 1000 -line = xt.Line.from_dict(input_data['line']) -particles = xp.Particles.from_dict(input_data['particle']) - -job_name = name -xb.prepare_job(name=name, user=user, job_name=job_name, num_turns=num_turns, line=line, particles=particles, checkpoint_every=100) - -#xb.prepare_study(name=name) -xb.submit_study(name=name, eosdir=eosdir) diff --git a/examples/004_submissions/002_submission.py b/examples/004_submissions/002_submission.py deleted file mode 100644 index ca2ee61..0000000 --- a/examples/004_submissions/002_submission.py +++ /dev/null @@ -1,56 +0,0 @@ -import os -import json -import glob -import tarfile -import itertools - -import numpy as np - -import xtrack as xt -import xpart as xp -import xboinc as xb - -import os, subprocess -from pathlib import Path -from time import sleep -import random - -user = 'ddicroce' # this should be read from a config json in the eos written by the boinc server -name = 'test' # study name - -filename = xt._pkg_root.parent.joinpath( - 'test_data/lhc_with_bb/line_and_particle.json') - -with open(filename, 'r') as fid: - input_data = json.load(fid) - - -# loop or anything that user wishes -nparticles = 6000 # approximate number of particles to be generated -ndims = 2 -dim_names = ['x', 'y'] -particles_per_dim = int(round(nparticles ** (1.0/ndims))) -coords = list(itertools.product(*[np.linspace(0, 1e-3, particles_per_dim) for i in range(ndims)])) - -particles_per_sub = 1000 -line = xt.Line.from_dict(input_data['line']) - -with xb.SubmitJobs(username=user, studyname=name) as job: - for i in range(0, len(coords), particles_per_sub): - job_id = job_id = i // particles_per_sub - job_name = f'{name}_{job_id}' - for j, dim_name in enumerate(dim_names): - input_data['particle'][dim_name] = [] - for coord in coords[i:i+particles_per_sub]: - for j, dim_name in enumerate(dim_names): - input_data['particle'][dim_name].append(coord[j]) - for dim_name in dim_names: - input_data['particle'][dim_name] = np.array(input_data['particle'][dim_name]) - - # Simulation input - num_turns = 1000 - particles = xp.Particles.from_dict(input_data['particle']) - - job.add(job_name=job_name, num_turns=num_turns, line=line, particles=particles, - checkpoint_every=100) - diff --git a/examples/register.py b/examples/register.py new file mode 100644 index 0000000..5e7464d --- /dev/null +++ b/examples/register.py @@ -0,0 +1,8 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + +import xboinc as xb + +xb.register('sixtadm','/afs/cern.ch/user/s/sixtadm/public/test_xboinc') diff --git a/examples/running/lossmap.py b/examples/running/lossmap.py new file mode 100644 index 0000000..1854b49 --- /dev/null +++ b/examples/running/lossmap.py @@ -0,0 +1,47 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + +import subprocess +from pathlib import Path +import numpy as np + +import xtrack as xt +import xpart as xp +import xcoll as xc +import xboinc as xb + + +# Create simulation input +num_turns = 20 +num_particles = 5000 +line = xt.Line.from_json(xc._pkg_root.parent / 'examples' / 'machines' / f'lhc_run3_b1.json') +coll_manager = xc.CollimatorManager.from_yaml(xc._pkg_root.parent / 'examples' / 'colldb' / f'lhc_run3.yaml', line=line, beam=1) +coll_manager.install_everest_collimators() +coll_manager.build_tracker() +coll_manager.set_openings() +part = coll_manager.generate_pencil_on_collimator('tcp.c6l7.b1', num_particles=num_particles) +coll_manager.enable_scattering() +xb.SimConfig.build(line=line, particles=part, num_turns=num_turns, filename='xboinc_input.bin', checkpoint_every=5) + + +# Run xboinc +cmd = subprocess.run(['uname', '-ms'], stdout=subprocess.PIPE) +architecture = cmd.stdout.decode('UTF-8').strip().lower().replace(' ','-') +exec_file = list(Path.cwd().glob(f'xboinc_{xb.app_version}-{architecture}')) +if len(exec_file)==0 or not exec_file[0].exists(): + raise ValueError("No executable found") +exec_file = exec_file[0] +cmd = subprocess.run(exec_file) +if cmd.returncode != 0: + raise RuntimeError(f"Tracking failed.") + + +# Read output +filename = 'sim_state_out.bin' +sim_state = xb.SimState.from_binary(filename) +part = sim_state.particles +_ = coll_manager.lossmap(part, file=Path(path_out,f'lossmap_B1H.json')) +summary = coll_manager.summary(part, file=Path(path_out,f'coll_summary_B1H.out')) +print(summary) diff --git a/examples/running/simple_line.py b/examples/running/simple_line.py new file mode 100644 index 0000000..098530b --- /dev/null +++ b/examples/running/simple_line.py @@ -0,0 +1,40 @@ +import subprocess +from pathlib import Path +import numpy as np + +import xtrack as xt +import xpart as xp +import xboinc as xb + + +# Create simulation input +num_turns = 200 +line = xt.Line(elements=[ + xt.Drift(length=1.0), xt.Multipole(knl=[1e-6]), xt.Drift(length=1.0)]) +particles = xp.Particles(mass0=xp.PROTON_MASS_EV, p0c=7e12, x=[1e-6,2e-6,3e-6]) +xb.SimConfig.build(line=line, particles=particles, num_turns=num_turns, + filename='xboinc_input.bin') + + +# Run xboinc +cmd = subprocess.run(['uname', '-ms'], stdout=subprocess.PIPE) +architecture = cmd.stdout.decode('UTF-8').strip().lower().replace(' ','-') +exec_file = list(Path.cwd().glob(f'xboinc_{xb.app_version}-{architecture}')) +if len(exec_file)==0 or not exec_file[0].exists(): + raise ValueError("No executable found") +exec_file = exec_file[0] +cmd = subprocess.run(exec_file) +if cmd.returncode != 0: + raise RuntimeError(f"Tracking failed.") + + +# Read output +filename = 'sim_state_out.bin' +sim_state = xb.SimState.from_binary(filename) +particles = sim_state.particles + +assert np.all(particles.s == 0) +assert np.all(particles.at_turn == num_turns) +assert sim_state.i_turn == num_turns + +print('All checks passed!') diff --git a/examples/running/xboinc_0.1-linux-x86_64 b/examples/running/xboinc_0.1-linux-x86_64 new file mode 100755 index 0000000..adc8adf Binary files /dev/null and b/examples/running/xboinc_0.1-linux-x86_64 differ diff --git a/examples/submission.py b/examples/submission.py new file mode 100644 index 0000000..9e57a55 --- /dev/null +++ b/examples/submission.py @@ -0,0 +1,32 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + + +import numpy as np + +import xtrack as xt +import xpart as xp +import xboinc as xb + + +user = 'sixtadm' + + +num_turns = 2000 +num_particles = 1e6 +line = xt.Line(elements=[ + xt.Drift(length=1.0), xt.Multipole(knl=[1e-6]), xt.Drift(length=1.0)]) + +particles_per_sub = 1000 + +studyname = "example_study" + +with xb.SubmitJobs(user=user, study=studyname) as job: + for i in range(int(num_particles/particles_per_sub)): + particles = xp.Particles(x=np.random.normal(0, 0.0001, particles_per_sub), + y=np.random.normal(0, 0.0001, particles_per_sub)) + job.add(job_name=f'{studyname}_{i}', num_turns=num_turns, line=line, particles=particles, + checkpoint_every=100) + diff --git a/pyproject.toml b/pyproject.toml index 5f46306..13f28bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "xboinc" -version = "0.1.2" +version = "0.1.3" description = "Xsuite BOINC interface" homepage = "https://github.com/xsuite/xboinc" repository = "https://github.com/xsuite/xboinc" diff --git a/tests/test_compilation_and_running.py b/tests/test_compilation_and_running.py new file mode 100644 index 0000000..b81fa67 --- /dev/null +++ b/tests/test_compilation_and_running.py @@ -0,0 +1,159 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + +import subprocess +import json +import numpy as np +from pathlib import Path +import os +import time +import filecmp + +import xtrack as xt +import xcoll as xc +import xboinc as xb + + +line_file = xc._pkg_root.parent / 'tests' / 'data' / 'sequence_lhc_run3_b1.json' +num_turns = 1000 + + +def test_compilation(): + source_files = xb.generate_executable_source() + assert Path(Path.cwd() / "main.c").exists() + assert Path(Path.cwd() / "sim_config.h").exists() + assert Path(Path.cwd() / "xtrack_tracker.h").exists() + + xb.generate_executable() + exec_file = list(Path.cwd().glob(f'xboinc_{xb.app_version}-*')) + assert len(exec_file) == 1 + assert exec_file[0].exists() + assert os.access(exec_file[0], os.X_OK) + + +def test_generate_input(): + # Simulation input + line = xt.Line.from_json(line_file) + line.build_tracker() + x_norm = np.linspace(-.5, .5, 50) + delta = np.linspace(-1.e-5, 1.e-5, 50) + part = line.build_particles(x_norm=x_norm, delta=delta, nemitt_x=3.5e-6, nemitt_y=3.5e-6) + + # Assemble data structure + xb.SimConfig.build(line=line, particles=part, num_turns=num_turns, checkpoint_every=10, + filename='xboinc_input.bin') + + input_file = Path.cwd() / "xboinc_input.bin" + assert input_file.exists() + + +def test_track(): + # If no executable is present, make one + exec_file = list(Path.cwd().glob(f'xboinc_{xb.app_version}-*')) + if len(exec_file)==0 or not exec_file[0].exists(): + xb.generate_executable() + exec_file = exec_file[0] + + # If no input file is present, make one + input_file = Path.cwd() / 'xboinc_input.bin' + if not input_file.exists(): + test_generate_input() + + # run xboinc tracker + t1 = time.time() + cmd = subprocess.run([exec_file]) + print(round(time.time() - t1, 1)) + if cmd.returncode != 0: + raise RuntimeError(f"Tracking failed.") + + # Read output + output_file = Path.cwd() / 'sim_state_out.bin' + assert output_file.exists() + sim_state = xb.SimState.from_binary(output_file) + + # Look at particles state + part_xboinc = sim_state.particles + assert np.allclose(part_xboinc.s, 0, rtol=1e-6, atol=0), "Unexpected s" + assert np.all(part_xboinc.at_turn == num_turns), "Unexpected survivals (particles)" + assert sim_state.i_turn == num_turns, "Unexpecteds survival (sim_state)" + + # Rename file for comparison in next test + output_file.rename(output_file.parent / f'{output_file.name}_2') + + +def test_checkpoint(): + # If no executable is present, make one + exec_file = list(Path.cwd().glob(f'xboinc_{xb.app_version}-*')) + if len(exec_file)==0 or not exec_file[0].exists(): + xb.generate_executable() + exec_file = exec_file[0] + + # If no input file is present, make one + input_file = Path.cwd() / 'xboinc_input.bin' + if not input_file.exists(): + test_generate_input() + + # If previous output file not present, we need to regenerate it (to be able to compare) + output_file = Path.cwd() / 'sim_state_out.bin_2' + if not output_file.exists(): + test_track() + + # run xboinc tracker and interrupt halfway + interrupted = False + timeout = 25 + print(f"Will interrupt after {timeout}s.") + try: + cmd = subprocess.run(exec_file, timeout=timeout) + except subprocess.TimeoutExpired: + interrupted = True + print("Interrupted calculation. Now trying to continue.") + checkpoint_file = Path.cwd() / 'checkpoint.bin' + assert checkpoint_file.exists() + if not interrupted: + raise ValueError("Timeout was too short. Adapt the test 'test_checkpoint'.") + + # Now continue tracking (without timeout) + cmd = subprocess.run(exec_file) + if cmd.returncode != 0: + raise RuntimeError(f"Tracking failed.") + + # Compare file to previous result + output_file = Path.cwd() / 'sim_state_out.bin' + assert output_file.exists() + assert filecmp.cmp(output_file, output_file.parent / f'{output_file.name}_2', shallow=False) + + +def test_vs_xtrack(): + # If no output is present, make one + output_file = Path.cwd() / 'sim_state_out.bin' + if not output_file.exists(): + test_track() + sim_state = xb.SimState.from_binary(output_file) + part_xboinc = sim_state.particles + + # Testing results with xtrack + line = xt.Line.from_json(line_file) + line.build_tracker() + x_norm = np.linspace(-.5, .5, 50) + delta = np.linspace(-1.e-5, 1.e-5, 50) + part = line.build_particles(x_norm=x_norm, delta=delta, nemitt_x=3.5e-6, nemitt_y=3.5e-6) + line.track(part, num_turns=num_turns) + + assert np.array_equal(part.at_turn, part_xboinc.at_turn), "Fail to match xtrack: survivals are not equal" + assert np.array_equal(part.x, part_xboinc.x), "Fail to match xtrack: x are not equal" + assert np.array_equal(part.y, part_xboinc.y), "Fail to match xtrack: y are not equal" + assert np.array_equal(part.zeta, part_xboinc.zeta), "Fail to match xtrack: zeta are not equal" + assert np.array_equal(part.px, part_xboinc.px), "Fail to match xtrack: px are not equal" + assert np.array_equal(part.py, part_xboinc.py), "Fail to match xtrack: py are not equal" + assert np.array_equal(part.delta, part_xboinc.delta), "Fail to match xtrack: delta are not equal" + + +def test_clean(): + input_files = list(Path.cwd().glob('xboinc_input.bin*')) + output_files = list(Path.cwd().glob('sim_state_out.bin*')) + exec_files = list(Path.cwd().glob(f'xboinc_{xb.app_version}-*')) + for file in [*input_files, *output_files, *exec_files]: + if file.exists(): + file.unlink() diff --git a/tests/test_generation.py b/tests/test_generation.py deleted file mode 100644 index a279cc6..0000000 --- a/tests/test_generation.py +++ /dev/null @@ -1,21 +0,0 @@ -import subprocess -import json -import numpy as np -from pathlib import Path -import os - -import xtrack as xt -import xpart as xp -import xboinc as xb - - -def test_compilation(): - source_files = xb.generate_executable_source() - assert Path(Path.cwd() / "main.c").exists() - assert Path(Path.cwd() / "sim_config.h").exists() - assert Path(Path.cwd() / "xtrack_tracker.h").exists() - - xb.generate_executable() - exec_file = Path.cwd() / "xboinc_executable" - assert exec_file.exists() - assert os.access(exec_file, os.X_OK) diff --git a/tests/test_track.py b/tests/test_track.py deleted file mode 100644 index 2b7cc32..0000000 --- a/tests/test_track.py +++ /dev/null @@ -1,97 +0,0 @@ -import subprocess -import json -import numpy as np -from pathlib import Path -import os - -import xtrack as xt -import xpart as xp -import xboinc as xb - - -test_line = xt._pkg_root.parent / 'test_data' / 'lhc_with_bb' / 'line_and_particle.json' -num_turns = 1000 - - -def test_generate_input(): - with test_line.open('r') as fid: - input_data = json.load(fid) - - # We add some particles - input_data['particle']['x'] += np.linspace(0, 1e-3, 10) - - # Simulation input - line = xt.Line.from_dict(input_data['line']) - particles = xp.Particles.from_dict(input_data['particle']) - - # Assemble data structure - xb.build_input_file(line=line, particles=particles, num_turns=num_turns, checkpoint_every=100, - name='xboinc_input.bin') - - input_file = Path.cwd() / "xboinc_input.bin" - assert input_file.exists() - - -def test_track(): - # If no executable is present, make one - exec_file = Path.cwd() / "xboinc_executable" - if not exec_file.exists(): - xb.generate_executable() - - # If no input file is present, make one - input_file = Path.cwd() / 'xboinc_input.bin' - if not input_file.exists(): - test_generate_input() - - # run xboinc tracker - cmd = subprocess.run([exec_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - if cmd.returncode != 0: - stderr = cmd.stderr.decode('UTF-8').strip().split('\n') - raise RuntimeError(f"Tracking failed. Stderr:\n {stderr}") - - # Read output - output_file = Path.cwd() / 'sim_state_out.bin' - assert output_file.exists() - sim_state = xb.read_output_file(output_file) - - # Look at particles state - particles_xboinc = sim_state.particles - - assert np.allclose(particles_xboinc.s, 0, rtol=1e-6, atol=0), "Unexpected s" - assert np.all(particles_xboinc.at_turn == num_turns), "Unexpected survivals (particles)" - assert sim_state.i_turn == num_turns, "Unexpecteds survival (sim_state)" - - -def test_vs_xtrack(): - # If no output is present, make one - output_file = Path.cwd() / 'sim_state_out.bin' - if not output_file.exists(): - test_track() - sim_state = xb.read_output_file(output_file) - particles_xboinc = sim_state.particles - - # Testing results with xtrack - with test_line.open('r') as fid: - input_data = json.load(fid) - input_data['particle']['x'] += np.linspace(0, 1e-3, 10) - line_xtrack = xt.Line.from_dict(input_data['line']) - particles = xp.Particles.from_dict(input_data['particle']) - line_xtrack.build_tracker() - line_xtrack.track(particles, num_turns=num_turns) - - assert np.array_equal(particles.at_turn, particles_xboinc.at_turn), "Fail to match xtrack: survivals are not equal" - assert np.array_equal(particles.x, particles_xboinc.x), "Fail to match xtrack: x are not equal" - assert np.array_equal(particles.y, particles_xboinc.y), "Fail to match xtrack: y are not equal" - assert np.array_equal(particles.zeta, particles_xboinc.zeta), "Fail to match xtrack: zeta are not equal" - assert np.array_equal(particles.px, particles_xboinc.px), "Fail to match xtrack: px are not equal" - assert np.array_equal(particles.py, particles_xboinc.py), "Fail to match xtrack: py are not equal" - assert np.array_equal(particles.delta, particles_xboinc.delta), "Fail to match xtrack: delta are not equal" - - -def test_clean(): - input_file = Path.cwd() / "xboinc_input.bin" - output_file = Path.cwd() / 'sim_state_out.bin' - exec_file = Path.cwd() / "xboinc_executable" - for file in [input_file, output_file, exec_file]: - if file.exists(): - file.unlink() diff --git a/tests/test_user.py b/tests/test_user.py new file mode 100644 index 0000000..21220b2 --- /dev/null +++ b/tests/test_user.py @@ -0,0 +1,35 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + +from pathlib import Path +import json +import pytest + +import xboinc as xb + +user = 'sixtadm' +folder_afs = Path('/afs/cern.ch/user/s/sixtadm/public/test_xboinc').resolve() +folder_eos = Path('/afs/cern.ch/user/s/sixtadm/eos_sixtadm/test_xboinc').resolve() + +user_data_file = xb._pkg_root / 'user_data.json' + + +def test_remove(): + xb.user.remove_user(user) + with user_data_file.open('r') as fid: + userdict = json.load(fid) + assert user not in userdict.keys() + + +def test_register(): + xb.register(user, folder_afs) + assert xb.user.get_folder(user) == folder_afs + assert xb.user.get_domain(user) == 'afs' + assert xb.user.get_user_data(user)['folder'] == folder_afs.as_posix() + assert xb.user.get_user_data(user)['domain'] == 'afs' + assert xb.server.eos.eos_exists(xb.server.paths.dropdir / f"register_{user}.json") + + with pytest.raises(NotImplementedError): + xb.register(user, folder_eos) diff --git a/tests/test_user_submission.py b/tests/test_user_submission.py new file mode 100644 index 0000000..413cb79 --- /dev/null +++ b/tests/test_user_submission.py @@ -0,0 +1,54 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + +import tarfile +import numpy as np +import pandas as pd + +import xtrack as xt +import xpart as xp +import xboinc as xb + + +user = 'sixtadm' + + +def test_submission(): + num_turns = 2000 + num_particles = 1e6 + line = xt.Line(elements=[ + xt.Drift(length=1.0), xt.Multipole(knl=[1e-6]), xt.Drift(length=1.0)]) + + particles_per_sub = 1000 + + studyname = "test_study" + num_jobs = int(num_particles/particles_per_sub) + + with xb.SubmitJobs(user=user, study=studyname) as job: + for i in range(num_jobs): + particles = xp.Particles(x=np.random.normal(0, 0.0001, particles_per_sub), + y=np.random.normal(0, 0.0001, particles_per_sub)) + job.add(job_name=f'{studyname}_{i}', num_turns=num_turns, line=line, particles=particles, + checkpoint_every=100) + + now = pd.Timestamp.now().timestamp() + tarfiles = list(xb.user.get_folder(user).glob(f'{studyname}__*')) + assert len(tarfiles) > 0 + # Look for the tar that is just generated + for tar in tarfiles: + ts = tar.name.split('__')[-1].split('.')[0].replace('_','T').replace('-', ':').replace(':', '-', 2) + if abs(now - pd.Timestamp(ts).timestamp()) < 60: + break + assert tar.exists() and tar.stat().st_size!=0 + tar_contents = tarfile.open(tar) + members = tar_contents.getmembers() + assert len(members) == 2*num_jobs + assert np.all([member.size > 8 for member in members]) + member_names = [member.name for member in members] + assert len(member_names) == 2*num_jobs + assert np.all([member[:len(user)+2] == f'{user}__' for member in member_names]) + assert len([member for member in member_names if member[-5:]=='.json']) == num_jobs + assert len([member for member in member_names if member[-4:]=='.bin']) == num_jobs + tar.unlink() diff --git a/tests/test_version.py b/tests/test_version.py index 97df0b0..3a779dc 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,5 +1,20 @@ +# copyright ############################### # +# This file is part of the Xboinc Package. # +# Copyright (c) CERN, 2023. # +########################################### # + +import pytest from xboinc import __version__ +from xboinc.simulation_io import SimVersion +from xboinc.simulation_io.version import _version_to_int, _int_to_version def test_version(): - assert __version__ == '0.1.2' + assert __version__ == '0.1.3' +def test_sim_ver(): + simver = SimVersion() + simver.assert_version() + print(_int_to_version(simver.xboinc_version)) + with pytest.raises(Exception): + simver.xboinc_version = _version_to_int('0.0.0') + simver.assert_version() diff --git a/xboinc/executable/main.c b/xboinc/executable/main.c index 6a346dc..2835f6b 100644 --- a/xboinc/executable/main.c +++ b/xboinc/executable/main.c @@ -90,10 +90,12 @@ int main(){ } int64_t step_turns; - if (checkpoint_every>0){ + if (checkpoint_every > 0){ step_turns = checkpoint_every; + printf("Checkpointing every %d turns\n", (int) step_turns); } else { - step_turns = num_elements; + step_turns = num_turns; + printf("Not checkpointing\n"); } while (current_turn < num_turns){ @@ -119,7 +121,7 @@ int main(){ SimStateData_set_i_turn(sim_state, SimStateData_get_i_turn(sim_state) + step_turns); current_turn = SimStateData_get_i_turn(sim_state); - if (checkpoint_every>0){ + if (checkpoint_every > 0){ if (current_turn < num_turns){ printf("Checkpointing turn %d\n", (int) current_turn); FILE *chkp_fid; @@ -146,10 +148,11 @@ int main(){ fclose(out_fid); // Remove checkpoint - if (remove("./checkpoint.bin") != 0){ - printf("Error: could not remove checkpoint file\n"); - return -1; // error + if (checkpoint_every > 0 && checkpoint_every < num_turns){ + if (remove("./checkpoint.bin") != 0){ + printf("Error: could not remove checkpoint file\n"); + return -1; // error + } } - return 0; } diff --git a/xboinc/general.py b/xboinc/general.py index 15ba19c..4b0394d 100644 --- a/xboinc/general.py +++ b/xboinc/general.py @@ -12,7 +12,7 @@ # Do not change # ========================================================================================== -__version__ = '0.1.2' +__version__ = '0.1.3' # These are the xsuite modules that are used by boinc and the versions they are tied to. # This will be automatically updated from the active environment when making a minor release. diff --git a/xboinc/register.py b/xboinc/register.py index 713620c..9067968 100644 --- a/xboinc/register.py +++ b/xboinc/register.py @@ -10,7 +10,7 @@ from .user import update_user_data from .server import server_account from .server.paths import dropdir -from .server.eos import eos_exists, eos_rm, cp_to_eos +from .server.eos import eos_exists, eos_rm, cp_to_eos, xrdcp_installed from .server.afs import afs_add_acl @@ -50,7 +50,7 @@ def register(user, folder): _set_rights(folder, data['domain']) except Exception as e: user_file.unlink() - raise Exception(e) + raise e if eos_exists(dropdir / user_file.name): eos_rm(dropdir / user_file.name) print("Replaced existing registration file on server dropdir.") diff --git a/xboinc/server/afs.py b/xboinc/server/afs.py index d00daec..dcbded2 100644 --- a/xboinc/server/afs.py +++ b/xboinc/server/afs.py @@ -5,6 +5,8 @@ import subprocess from pathlib import Path +from time import sleep +import random from .tools import log_debug, log_info, log_error diff --git a/xboinc/simulation_io/input.py b/xboinc/simulation_io/input.py index cb7e653..0d3722b 100644 --- a/xboinc/simulation_io/input.py +++ b/xboinc/simulation_io/input.py @@ -30,6 +30,8 @@ def build(cls, *, num_turns, line, particles, checkpoint_every=-1, filename=None simbuf = xo.ContextCpu().new_buffer() sim_config = cls(_buffer=simbuf) default_tracker = _default_tracker + line.discard_tracker() + # TODO: check that line does not contain non-supported elements line.build_tracker(_context=simbuf.context, _buffer=simbuf, track_kernel=default_tracker.track_kernel) if _default_config_hash not in line.tracker._tracker_data_cache: diff --git a/xboinc/submit.py b/xboinc/submit.py index dc45d95..3f5ce47 100644 --- a/xboinc/submit.py +++ b/xboinc/submit.py @@ -10,13 +10,11 @@ from .user import get_domain, get_folder from .server.eos import mv_from_eos, mv_to_eos, xrdcp_installed +from .server.afs import mv_from_afs, mv_to_afs from .server.tools import timestamp from .simulation_io import SimConfig, app_version -eosdir = '/eos/user/d/ddicroce/xboinc/' - - class SubmitJobs: def __init__(self, user, study): @@ -25,14 +23,14 @@ def __init__(self, user, study): self._username = user self._domain = get_domain(user) if self._domain=='eos' and not xrdcp_installed(): - raise ValueError("Error: xrdcp is not installed on your system. Cannot submit.") + raise ValueError("Error: xrdcp is not installed on your system. Cannot submit to EOS.") self._target = get_folder(user) self._studyname = study self._submitfile = f"{self._studyname}__{timestamp()}.tar.gz" self._json_files = [] self._bin_files = [] self._temp = tempfile.TemporaryDirectory() - self._tempdir = Path(temp.name).resolve() + self._tempdir = Path(self._temp.name).resolve() self._tempdir.mkdir(parents=True, exist_ok=True) def __enter__(self, *args, **kwargs): diff --git a/xboinc/user.py b/xboinc/user.py index c02ff35..009ddb3 100644 --- a/xboinc/user.py +++ b/xboinc/user.py @@ -36,3 +36,12 @@ def get_folder(user): def get_domain(user): return get_user_data(user)['domain'] + +def remove_user(user): + with user_data_file.open('r') as fid: + userdict = json.load(fid) + if user in userdict: + userdict.pop(user) + with user_data_file.open('w') as fid: + json.dump(userdict, fid) +