From 66efd3dea9482a69681be33b05e9ed442a6c0578 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 11 Apr 2023 18:18:03 +0200 Subject: [PATCH 1/5] purge devtools: rm line counting tools --- devtools/linecount/baloc/__init__.py | 3 - devtools/linecount/baloc/file_types.py | 122 ----------------- devtools/linecount/baloc/history_collector.py | 128 ------------------ devtools/linecount/baloc/history_plot.py | 63 --------- devtools/linecount/lines_of_code.py | 58 -------- 5 files changed, 374 deletions(-) delete mode 100644 devtools/linecount/baloc/__init__.py delete mode 100644 devtools/linecount/baloc/file_types.py delete mode 100644 devtools/linecount/baloc/history_collector.py delete mode 100644 devtools/linecount/baloc/history_plot.py delete mode 100755 devtools/linecount/lines_of_code.py diff --git a/devtools/linecount/baloc/__init__.py b/devtools/linecount/baloc/__init__.py deleted file mode 100644 index c8a9d7cc449..00000000000 --- a/devtools/linecount/baloc/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .file_types import * -from .history_collector import * -from .history_plot import * diff --git a/devtools/linecount/baloc/file_types.py b/devtools/linecount/baloc/file_types.py deleted file mode 100644 index 9a86fccbd53..00000000000 --- a/devtools/linecount/baloc/file_types.py +++ /dev/null @@ -1,122 +0,0 @@ -""" -Contains machinery to convert BornAgain filename to the type of the content -""" - -class FileTypes: - """ - Enumerator class to hold file types - """ - CORE, FTEST, UTEST, PYCODE, MACROS, GUI, PYAPI, THIRD, UNDEF, TOTAL = range(10) - descr=["Core", "Functional Tests", "Unit Tests", "*.py", "macros", "GUI", "PythonAPI", "Third", "Undef"] - @staticmethod - def loc_for_type(): - result = [] - for i in range(FileTypes.TOTAL): - result.append(0) - return result - - -def filePython(x): - if ".py" in x and not ".pypp." in x: return True - return False - - -def fileCpp(x): - if ".h" in x or ".cpp" in x: return True - return False - - -def dirCore(x): - # if "/Core/Algorithms" in x: return True - # if "/Core/FormFactors" in x: return True - # if "/Core/Samples" in x: return True - # if "/Core/StandardSamples" in x: return True - # if "/Core/Tools" in x: return True - # if "/Core/Fitting" in x: return True - # if "/Core/inc" in x: return True - # if "/Core/src" in x: return True - # if "/Core/InputOutput" in x: return True - # if "/Core/Geometry" in x: return True - # if "/Fit/Factory" in x: return True - # if "/Fit/FitKernel" in x: return True - # if "/Fit/StandardFits" in x: return True - # if "/Core/Geometry" in x: return True - if "/Core/" in x: return True - if "/Fit/" in x: return True - - return False - - -def dirPyAPI(x): - if "/Core/PythonAPI" in x: return True - if "/Fit/PythonAPI" in x: return True - return False - - -def dirFuncTest(x): - # if "/App/" in x: return True - if "/Tests/Functional" in x: return True - if "/Tests/PerformanceTests" in x: return True - if "/Tests/FunctionalTests/TestCore" in x: return True - if "/Tests/FunctionalTests/TestFit" in x: return True - if "/Tests/FunctionalTests/TestPyCore" in x: return True - if "/Tests/FunctionalTests/TestPyFit" in x: return True - if "/Core/TestMachinery" in x: return True - return False - - -def dirGUI(x): - if "/GUI/coregui" in x and not "widgetbox" in x and not "qttools" in x: return True - if "/GUI/main" in x: return True - if "/AppGUI/coregui" in x: return True - if "/BASuite" in x: return True - return False - - -def dirThirdParty(x): - if "/ThirdParty" in x: return True - return False - - -def dirSkip(x): - if "/pub/core" in x: return True - return False - - -def dirUnitTests(x): - if "/UnitTests/" in x: return True - if "/Tests/UnitTests/TestCore/" in x: return True - if "/Tests/UnitTests/TestFit/" in x: return True - if "/Tests/UnitTests/" in x: return True - return False - - -def filetype(x): - """ - Returns type of file - """ - result = FileTypes.UNDEF - - if dirSkip(x): - return result - - if dirPyAPI(x): - result = FileTypes.PYAPI - - elif dirThirdParty(x): - result = FileTypes.THIRD - - elif (fileCpp(x) or filePython(x)) and dirFuncTest(x): - result = FileTypes.FTEST - - elif fileCpp(x) and dirCore(x): - result = FileTypes.CORE - - elif dirUnitTests(x): - result = FileTypes.UTEST - - elif dirGUI(x): - result = FileTypes.GUI - - return result - diff --git a/devtools/linecount/baloc/history_collector.py b/devtools/linecount/baloc/history_collector.py deleted file mode 100644 index 8ac42f65e6d..00000000000 --- a/devtools/linecount/baloc/history_collector.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -Process gitlog and create a file with number of lines of code. -""" -from datetime import datetime -from .file_types import FileTypes, filetype -import re -from email.utils import parsedate -import subprocess - - -def gitlog(): - """ - Execute gitlog command and make generator over lines in the log - """ - p = subprocess.Popen(['git', 'log', 'develop', '--reverse', '-p'], stdout=subprocess.PIPE) - for line in iter(p.stdout.readline, b''): - decoded = line.decode('latin1') - if decoded and len(decoded): - yield decoded.strip() - - -class Commit: - """ - Contains commit info and accumulated number of lines of code (file type dependent). - """ - def __init__(self): - self.date = datetime.today() - self.added_lines = 0 - self.removed_lines = 0 - self.loc_for_type = FileTypes.loc_for_type() - self.hsh = None - self.who = None - self.cmt = None - - def increment_loc(self, file_type): - self.loc_for_type[file_type] += 1 - self.added_lines += 1 - - def decrement_loc(self, file_type): - self.loc_for_type[file_type] -= 1 - self.removed_lines += 1 - - -class DayHistory: - """ - Number of lines added or deleted for given day. - """ - def __init__(self, date, locs): - self.date = date - self.loc_for_type = locs - - -class HistoryCollector: - def __init__(self): - self.last_commit = Commit() - self.data = [] - self.locs = 0 - self.fc = 0 - self.file_type_ppp = FileTypes.UNDEF - self.file_type_mmm = FileTypes.UNDEF - self.start_date = datetime(2012, 4, 1) - self.days_history = {} # DayHistory vs. number of days since beginning of coding - - def pop(self): - if not self.last_commit.added_lines: - return - pstr="%s %8u %5s %5s %7s %s"%(self.last_commit.date, self.locs, '+' + str(self.last_commit.added_lines), '-' + str(self.last_commit.removed_lines), self.last_commit.hsh, self.last_commit.who) - print(pstr) - delta = (self.last_commit.date - self.start_date).days - self.days_history[delta] = DayHistory(self.last_commit.date, self.last_commit.loc_for_type) - - tmp = list(self.last_commit.loc_for_type) - self.last_commit = Commit() - self.last_commit.loc_for_type = tmp - - def run(self): - nnn = 0 - for x in gitlog(): - nnn += 1 - if x.startswith('commit'): - self.pop() - self.last_commit.hsh = x[7:14] - - if x.startswith('Author'): - self.last_commit.who = x.replace("Author: ", '').replace('\n', '') - self.last_commit.who = re.sub(">.*", "", self.last_commit.who) - self.last_commit.who = re.sub(".*<", "", self.last_commit.who) - - if x.startswith('Date'): - self.fc = 1 - self.last_commit.date = datetime(*parsedate(x[5:])[:7]) - - if self.fc == 2: - self.last_commit.cmt = x[:-1] - self.fc = 0 - - if self.fc == 1: - if len(x) == 1: - self.fc = 2 - - if x.startswith('+++'): - self.file_type_ppp = filetype(x) - - if x.startswith('---'): - self.file_type_mmm = filetype(x) - - if x.startswith('+') and not x.startswith('+++'): - self.last_commit.increment_loc(self.file_type_ppp) - if self.file_type_ppp <FileTypes.PYAPI: - self.locs += 1 - - if x.startswith('-') and not x.startswith('---'): - self.last_commit.decrement_loc(self.file_type_mmm) - if self.file_type_mmm < FileTypes.PYAPI: - self.locs -= 1 - - # if nnn>1000000: - # break - - self.pop() - - def save_report(self, filename): - print("Saving report in {0}".format(filename)) - with open(filename, 'w') as the_file: - for key in self.days_history: - dayhist = self.days_history[key] - pstr = "%s %s \n" % (str(dayhist.date), ' '.join(str(e) for e in dayhist.loc_for_type)) - the_file.write(pstr) diff --git a/devtools/linecount/baloc/history_plot.py b/devtools/linecount/baloc/history_plot.py deleted file mode 100644 index 73eabfc5792..00000000000 --- a/devtools/linecount/baloc/history_plot.py +++ /dev/null @@ -1,63 +0,0 @@ -import matplotlib.pyplot as plt -import seaborn as sns -from datetime import datetime -from .file_types import FileTypes, filetype - - -selected_file_type = [FileTypes.CORE, FileTypes.FTEST, FileTypes.UTEST, FileTypes.GUI, FileTypes.PYAPI] - - -def read_history(filename): - xvals = [] # Time - ydata = {} # id of file type .vs. LOC .vs. time - for x in selected_file_type: - ydata[x] = [] - - print("Reading file {0}".format(filename)) - with open(filename, 'r') as the_file: - for line in the_file: - parts = line.strip().split() - date = datetime.strptime(parts[0] + " " + parts[1], '%Y-%m-%d %H:%M:%S') - xvals.append(date) - for x in selected_file_type: - ydata[x].append(int(parts[2+x])) - - yvals = [] - descr = [] - for key in ydata: - descr.append(FileTypes.descr[key]) - yvals.append(ydata[key]) - - # printing summary of LOC - for x in range(0, len(yvals)): - print("{:18} : {:10}".format(descr[x], yvals[x][-1])) - - return xvals, yvals, descr - - -def history_plot(filename): - xvals, yvals, descr = read_history(filename) - - # figure size - my_dpi = 96 - plt.figure(figsize=(1600*1.2 / my_dpi, 900*1.2 / my_dpi), dpi=my_dpi) - plt.style.use('seaborn-bright') - - # making stackplot - plt.stackplot(xvals, yvals) - pal = ["#3399ff", "#ffcc00", "#ff0000", "#0033ff", "#999999"] - plt.stackplot(xvals, yvals, labels=descr, colors=pal) - - # styling axes and grid - plt.grid(color='gray', linestyle='dashed') - ax = plt.gca() - ax.set_axisbelow(True) - plt.ylim(0.0, 220e+03) - plt.tick_params(axis='both', which='major', labelsize=14) - - # making inverse legend - handles, labels = ax.get_legend_handles_labels() - ax.legend(handles[::-1], labels[::-1], loc='upper left', prop={'size': 18}) - - # saving plot - plt.savefig('lines_of_code.png', dpi=my_dpi, bbox_inches='tight') diff --git a/devtools/linecount/lines_of_code.py b/devtools/linecount/lines_of_code.py deleted file mode 100755 index 2366fa6f5a4..00000000000 --- a/devtools/linecount/lines_of_code.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -""" -Creates picture with number of lines of code. -Usage: python3 lines_of_code.py - -The command should be executed in the directory where lines_of_code.py is located -(i.e. in <BornAgain>/devtools/linecount) -""" -import sys -if sys.version_info < (3, 0): - exit("Requires python3, exiting ...") -import os -from baloc import HistoryCollector -from baloc import history_plot -import matplotlib.pyplot as plt - - -gitlog_filename = "gitlog.tmp" - - -def process_loc_number(targetfolder="../..", gitlog=gitlog_filename): - prevfolder = os.getcwd() - os.chdir(targetfolder) - - collector = HistoryCollector() - collector.run() - collector.save_report(os.path.join(prevfolder, gitlog)) - - os.chdir(prevfolder) - - -def plot_loc_number(gitlog=gitlog_filename): - history_plot(gitlog) - plt.show() - - -if __name__ == '__main__': - print('-' * 80) - print("Generating picture for number of lines of code") - print('-' * 80) - print(" ") - print("Possible options:") - print("[0] - Generate {0} and picture.".format(gitlog_filename)) - print("[1] - Generate only {0}.".format(gitlog_filename)) - print("[2] - Generate picture using existing {0}.".format(gitlog_filename)) - print("[3] - Exit") - - var = int(input("Enter your choice [0]: ") or "0") - - if var == 0: - process_loc_number() - plot_loc_number() - elif var == 1: - process_loc_number() - elif var == 2: - plot_loc_number() - else: - exit("Good bye") -- GitLab From 06c790a1be052e12f78daa09013330f182541641 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 11 Apr 2023 18:21:56 +0200 Subject: [PATCH 2/5] devtools: script names uniformly with hyphen --- Tests/Suite/Persist/Check.cpp | 4 ++-- devtools/view/{plot_diff_int.py => plot-diff.py} | 0 devtools/view/{plot_int.py => plot-int.py} | 0 devtools/view/{plot_numpy_array.py => plot-np-array.py} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename devtools/view/{plot_diff_int.py => plot-diff.py} (100%) rename devtools/view/{plot_int.py => plot-int.py} (100%) rename devtools/view/{plot_numpy_array.py => plot-np-array.py} (100%) diff --git a/Tests/Suite/Persist/Check.cpp b/Tests/Suite/Persist/Check.cpp index 7a40ca9d0b2..4c09ffd4b9f 100644 --- a/Tests/Suite/Persist/Check.cpp +++ b/Tests/Suite/Persist/Check.cpp @@ -61,9 +61,9 @@ bool checkSimulation(const std::string& name, ISimulation& direct_simulation, co BaseUtils::Filesystem::jointPath(BATesting::TestOutDir_Suite(), name + ".int.gz"); IOFactory::writeDatafield(*result_data, out_fname); std::cout << "Notes:\n- to visualize an intensity map, use " << BABuild::srcDir() - << "/devtools/view/plot_int.py\n" + << "/devtools/view/plot-int.py\n" << "- to plot a difference image, use " << BABuild::srcDir() - << "/devtools/view/plot_diff_int.py\n" + << "/devtools/view/plot-diff.py\n" << "- if the new simulation result\n" << " " << out_fname << "\n" << " is correct, then move it to the reference directory\n" diff --git a/devtools/view/plot_diff_int.py b/devtools/view/plot-diff.py similarity index 100% rename from devtools/view/plot_diff_int.py rename to devtools/view/plot-diff.py diff --git a/devtools/view/plot_int.py b/devtools/view/plot-int.py similarity index 100% rename from devtools/view/plot_int.py rename to devtools/view/plot-int.py diff --git a/devtools/view/plot_numpy_array.py b/devtools/view/plot-np-array.py similarity index 100% rename from devtools/view/plot_numpy_array.py rename to devtools/view/plot-np-array.py -- GitLab From 866e9134cbaf98842c45dab4f2590006632c0a01 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 11 Apr 2023 18:23:52 +0200 Subject: [PATCH 3/5] devtools: rm MPI scripts --- devtools/mpi/pytests/mpi_cpp_test.py | 76 -------------------- devtools/mpi/pytests/mpi_test.py | 103 --------------------------- devtools/mpi/pytests/version.py | 2 - devtools/mpi/supermuc.sh | 17 ----- 4 files changed, 198 deletions(-) delete mode 100644 devtools/mpi/pytests/mpi_cpp_test.py delete mode 100644 devtools/mpi/pytests/mpi_test.py delete mode 100644 devtools/mpi/pytests/version.py delete mode 100644 devtools/mpi/supermuc.sh diff --git a/devtools/mpi/pytests/mpi_cpp_test.py b/devtools/mpi/pytests/mpi_cpp_test.py deleted file mode 100644 index ccc8774a3d5..00000000000 --- a/devtools/mpi/pytests/mpi_cpp_test.py +++ /dev/null @@ -1,76 +0,0 @@ -# Mixture of cylinders and prisms without interference - -from mpi4py import MPI # this line has to be first -import numpy -import matplotlib -import pylab -from libBornAgainCore import * - -comm = MPI.COMM_WORLD -world_size = comm.Get_size() -world_rank = comm.Get_rank() - - -def get_sample(): - """ - Build and return the sample representing cylinders and pyramids on top of - substrate without interference. - """ - # defining materials - m_air = HomogeneousMaterial("Air", 0.0, 0.0) - m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8) - m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8) - - # collection of particles - cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer) - cylinder = Particle(m_particle, cylinder_ff) - prism_ff = FormFactorPrism3(10*nanometer, 5*nanometer) - prism = Particle(m_particle, prism_ff) - particle_layout = ParticleLayout() - particle_layout.addParticle(cylinder, 0.5) - particle_layout.addParticle(prism, 0.5) - - # air layer with particles and substrate form multi layer - air_layer = Layer(m_air) - air_layer.addLayout(particle_layout) - substrate_layer = Layer(m_substrate) - multi_layer = MultiLayer() - multi_layer.addLayer(air_layer) - multi_layer.addLayer(substrate_layer) - return multi_layer - - -def get_simulation(): - """ - Create and return GISAS simulation with beam and detector defined - """ - simulation = GISASSimulation() - simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree) - simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) - sample = get_sample() - simulation.setSample(sample) - - return simulation - - -def run_simulation(): - """ - Run simulation and plot results - """ - simulation = get_simulation() - - if(world_size == 1): - print("Not an MPI environment, run with 'mpirun -n 4 python ompi_sim_example.py'") - exit(0) - - simulation.runMPISimulation() - - if(world_rank == 0): - sumresult = simulation.result().array() - print(sumresult) - # pylab.imshow(sumresult + 1, norm=matplotlib.colors.LogNorm(), extent=[-1.0, 1.0, 0, 2.0]) - # pylab.show() - - -if __name__ == '__main__': - run_simulation() diff --git a/devtools/mpi/pytests/mpi_test.py b/devtools/mpi/pytests/mpi_test.py deleted file mode 100644 index 367c46d41a7..00000000000 --- a/devtools/mpi/pytests/mpi_test.py +++ /dev/null @@ -1,103 +0,0 @@ -# Mixture of cylinders and prisms without interference (IsGISAXS example ex-1) - -from mpi4py import MPI # this line has to be first -import numpy -import matplotlib -import pylab -from libBornAgainCore import * - -comm = MPI.COMM_WORLD -world_size = comm.Get_size() -world_rank = comm.Get_rank() - - -def get_sample(): - """ - Build and return the sample representing cylinders and pyramids on top of - substrate without interference. - """ - # defining materials - m_air = HomogeneousMaterial("Air", 0.0, 0.0) - m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8) - m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8) - - # collection of particles - cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer) - cylinder = Particle(m_particle, cylinder_ff) - prism_ff = FormFactorPrism3(10*nanometer, 5*nanometer) - prism = Particle(m_particle, prism_ff) - particle_layout = ParticleLayout() - particle_layout.addParticle(cylinder, 0.5) - particle_layout.addParticle(prism, 0.5) - - # air layer with particles and substrate form multi layer - air_layer = Layer(m_air) - air_layer.addLayout(particle_layout) - substrate_layer = Layer(m_substrate) - multi_layer = MultiLayer() - multi_layer.addLayer(air_layer) - multi_layer.addLayer(substrate_layer) - return multi_layer - - -def get_simulation(): - """ - Create and return GISAXS simulation with beam and detector defined - """ - simulation = GISASSimulation() - simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree) - simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) - sample = get_sample() - simulation.setSample(sample) - - return simulation - - -def run_simulation(): - """ - Run simulation and plot results - """ - simulation = get_simulation() - - if(world_size == 1): - print("Not a MPI environment, run with 'mpirun -n 4 python ompi_sim_example.py'") - exit(0) - - if(world_rank != 0): - options = simulation.getOptions() - thread_info = ThreadInfo() - thread_info.n_threads = options.getNumberOfThreads() - thread_info.n_batches = world_size - 1 - thread_info.current_batch = world_rank - 1 - options.setThreadInfo(thread_info) - simulation.setOptions(options) - print("preparing to run ", thread_info.n_batches, thread_info.current_batch) - simulation.runSimulation() - print("preparing to send") - comm.Send(simulation.result().array(), 0) - - if(world_rank == 0): - sumresult = simulation.result().array() - print(sumresult) - sumresult = numpy.zeros(sumresult.shape) - print(sumresult) - - print("preparing to receive") - for i_proc in range(1, world_size): - print(" ... receiving", i_proc) - result = numpy.zeros(sumresult.shape) - comm.Recv(result, i_proc) - sumresult += result - print(sumresult) - - if(world_rank == 0): - print(sumresult) - # pylab.imshow(sumresult + 1, norm=matplotlib.colors.LogNorm(), extent=[-1.0, 1.0, 0, 2.0]) - # pylab.show() - - -if __name__ == '__main__': - run_simulation() - - - diff --git a/devtools/mpi/pytests/version.py b/devtools/mpi/pytests/version.py deleted file mode 100644 index 261a6512c03..00000000000 --- a/devtools/mpi/pytests/version.py +++ /dev/null @@ -1,2 +0,0 @@ -import sys -print(sys.version) diff --git a/devtools/mpi/supermuc.sh b/devtools/mpi/supermuc.sh deleted file mode 100644 index ce93ec8cdb5..00000000000 --- a/devtools/mpi/supermuc.sh +++ /dev/null @@ -1,17 +0,0 @@ -# Setup for BornAgain compilation at SuperMUC LRZ cluster - - -module load git -module load gcc/4.7 -module load cmake/2.8 -module load fftw/mpi/3.3 -module load gsl -#module load python/2.7_anaconda - -export LD_LIBRARY_PATH=/home/hpc/pr87me/di29sok/software/boost_1_55_0.gcc47/lib:$LD_LIBRARY_PATH - -export FFTW3=$FFTW_BASE -export GSL_DIR=$GSL_BASE -export BOOST_ROOT=/home/hpc/pr87me/di29sok/software/boost_1_55_0.gcc47 - - -- GitLab From e42cc010278df81bb1c1c6e3a1bb0580d8843d81 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 11 Apr 2023 18:24:44 +0200 Subject: [PATCH 4/5] devtools: update README --- devtools/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/devtools/README.md b/devtools/README.md index bdfb625a80e..19f7ec8d2fa 100644 --- a/devtools/README.md +++ b/devtools/README.md @@ -1,4 +1 @@ -Various tools for BornAgain developers. - -Note that this directory receives only little, and irregular, attention. -Much of the material is outdated or obsolete. +Various tools for BornAgain maintainers. -- GitLab From 3f2f83102b1e433a5e7fd2a435202a01e9b99f11 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 11 Apr 2023 18:25:08 +0200 Subject: [PATCH 5/5] devtools: rm outdated architecture analyses --- devtools/architecture/DepthProbe.md | 32 ----- devtools/architecture/Lattice.md | 21 --- .../architecture/ParameterDistribution.md | 117 ---------------- devtools/architecture/Scattering.md | 126 ------------------ 4 files changed, 296 deletions(-) delete mode 100644 devtools/architecture/DepthProbe.md delete mode 100644 devtools/architecture/Lattice.md delete mode 100644 devtools/architecture/ParameterDistribution.md delete mode 100644 devtools/architecture/Scattering.md diff --git a/devtools/architecture/DepthProbe.md b/devtools/architecture/DepthProbe.md deleted file mode 100644 index 2ee5e194979..00000000000 --- a/devtools/architecture/DepthProbe.md +++ /dev/null @@ -1,32 +0,0 @@ -## How does BornAgain compute depth profiles - -Analysis of BornAgain v1.19.0 - -### Simulation computes an incoherent sum - -We consider a simulation handled by class `DepthProbeSimulation < ISimulation` -(where `<` indicates inheritance). - -The function `ISimulation::runSimulation` -- calls `ISimulation::prepareSimulation`, which - - does nothing of interest, except for sample builders -- loops over parameter combinations, thereby performing an incoherent summation: - - for each parameter set, `runSingleSimulation`; -- calls `DepthProbeSimulation::moveDataFromCache` to collect results. - - also calls `transferResultsToIntensityMap`, which does nothing except for `OffSpecSimulation`. - -`ISimulation::runSingleSimulation` handles the multithreaded parallel computation -for batches of detector pixels (`SimulationElement`s). It -- uses `DepthProbeSimulation::generateSingleThreadedComputation` - to create instances of `DepthProbeComputation < IComputation`; -- for each instance, runs `IComputation.run`; -- calls `ISimulation2D::normalize`; -- calls `ISimulation2D::addBackgroundIntensity`. - -The `IComputation` constructor creates the member `ProcessedSample m_processed_sample`. - -The `DepthProbeComputation` constructor - sets the member `DepthProbeComputationTerm m_computation_term` - using `ProcessedSample` ...?... - -`DepthProbeComputationTerm::compute` computes intensities for all z at one alpha_i. diff --git a/devtools/architecture/Lattice.md b/devtools/architecture/Lattice.md deleted file mode 100644 index 8c6d38792c4..00000000000 --- a/devtools/architecture/Lattice.md +++ /dev/null @@ -1,21 +0,0 @@ -## Lattices - -Typical sample construction with a 3d lattice: -``` - lattice = ba.FCCLattice(30*nm).transformed(rot.getTransform3D()) - peak_shape = ba.MisesFisherGaussPeakShape(peak_intensity, peak_width, zenith, kappa, kappa2) - iff = ba.InterferenceFunction3DLattice(lattice) - iff.setPositionVariance(1.) - iff.setPeakShape(peak_shape) - - layout = ba.ParticleLayout() - layout.addParticle(particle) - layout.setTotalParticleSurfaceDensity(.01) - layout.setInterferenceFunction(iff) - layout.setWeight(1.0) - - vacuum_layer = ba.Layer(m_vacuum) - vacuum_layer.addLayout(layout) -``` - -`bake::FCCLattice` returns a `Lattice3d` with an fcc primitive cell. diff --git a/devtools/architecture/ParameterDistribution.md b/devtools/architecture/ParameterDistribution.md deleted file mode 100644 index 1c774260c98..00000000000 --- a/devtools/architecture/ParameterDistribution.md +++ /dev/null @@ -1,117 +0,0 @@ -## Parameter distributions - -Analysis of BornAgain develop, per 3dec20. - -It seems there are two different ways for handling parameter distributions, -the one specifically for particle distributions, the other one more generic. - -### Particle distribution - -#### Typical use - -Typical use of parameter distributions is described in -`Examples/Python/sim01_Particles/CylindersWithSizeDistribution.py`: -``` -def get_sample(): - # Define materials and form factor ... - - # Define particles - particle = ba.Particle(material_Particle, ff) - - # Define particles with parameter following a distribution - distr_1 = ba.DistributionGaussian(5.0*nm, 1.0*nm) - par_distr_1 = ba.ParameterDistribution( - "/Particle/Cylinder/Radius", distr_1, 100, 2.0) - particle_distrib = ba.ParticleDistribution(particle, par_distr_1) - - # Define particle layouts - layout = ba.ParticleLayout() - layout.addParticle(particle_distrib, 1.0) - - # Define layers - layer = ba.Layer(material_Vacuum) - layer.addLayout(layout) - - # Define sample - sample = ba.MultiLayer() - sample.addLayer(layer) - - return sample - - -def get_simulation(): - simulation = ba.ScatteringSimulation() - simulation.setDetectorParameters(200, 0.0*deg, 2.0*deg, 200, 0.0*deg, 2.0*deg) - simulation.setBeamParameters(1.0*angstrom, 0.2*deg, 0.0*deg) - return simulation - - -def run_simulation(): - simulation = get_simulation() - simulation.setSample(get_sample()) - simulation.runSimulation() - return simulation.result() -``` - -#### What goes on behind the scenes? - -Class hierarchy: -``` -IParametricComponent -- INode - - ISampleNode - - IAbstractParticle - - ParticleDistribution (final) - - IParticle - - Particle (final) - - CoreAndShell (final) - ... (all final) -- ISampleBuilder -- DistributionHandler (final) -- ParameterDistribution (final) -``` - -As we see from the `CylindersWithSizeDistribution` example, -a `ParticleDistribution` is bound to a `ParticleLayout`. -The drawing of `IParticle`s from the distribution happens here: - -``` -SafePointerVector<IParticle> ParticleLayout::particles() const { - SafePointerVector<IParticle> particle_vector; - for (const auto* particle : m_particles) { - if (const auto* p_part_distr = dynamic_cast<const ParticleDistribution*>(particle)) { - SafePointerVector<IParticle> generated_particles = p_part_distr->generateParticles(); - for (const IParticle* particle : generated_particles) - particle_vector.push_back(particle->clone()); - } else if (const auto* p_iparticle = dynamic_cast<const IParticle*>(particle)) { - particle_vector.push_back(p_iparticle->clone()); - } - } - return particle_vector; -} -``` - -### Generic distribution handler - -This mechanism acts almost on top of the simulation model hierarchy. - -`ISimulation` has member `DistributionHandler m_distribution_handler`. -It is modified through `ISimulation::addParameterDistribution`. -This function is called explicitly by some standard simulations and Python scripts -(e.g. `sim03_Structures/Interference2DLatticeSumOfRotated.py`), -but not in the above simple example. - - -``` -void ISimulation::runSimulation() { - ... - size_t param_combinations = m_distribution_handler.getTotalNumberOfSamples(); - std::unique_ptr<ParameterPool> param_pool(createParameterTree()); - for (size_t index = 0; index < param_combinations; ++index) { - double weight = m_distribution_handler.setParameterValues(param_pool.get(), index); - runSingleSimulation(batch_start, batch_size, weight); - } - m_distribution_handler.setParameterToMeans(param_pool.get()); - ... -} -``` diff --git a/devtools/architecture/Scattering.md b/devtools/architecture/Scattering.md deleted file mode 100644 index ca15543a9f9..00000000000 --- a/devtools/architecture/Scattering.md +++ /dev/null @@ -1,126 +0,0 @@ -## How does BornAgain compute scattering? - -Analysis of BornAgain develop -- per 18nov20, after merge of https://github.com/scgmlz/BornAgain/pull/1105 -- partly checked and improved 24jun21 - -### Run parallel simulations - -We consider a GISAS simulation, handled by class `ScatteringSimulation < ISimulation2D < ISimulation` -(where `<` indicates inheritance). - -The function `ScatteringSimulation::runSimulation` -- calls `ISimulation::prepareSimulation`; - - calls `Instrument::initDetector`, - - calls `ISimulation2D::prepareSimulation` - - calls `ISimulation::prepareSimulation` - - does nothing of interest, except for sample builders - - calls `IDetector2D::createContext` -- loops over parameter combinations, thereby performing an incoherent summation: - - for each parameter set, `runSingleSimulation`; -- calls `ISimulation2D::moveDataFromCache` to collect results. - - also calls `transferResultsToIntensityMap`, which does nothing except for `OffSpecSimulation`. - -`ScatteringSimulation::prepareSimulation` seems to be mostly concerned with `SampleBuilder`s. - -`ISimulation::runSingleSimulation` handles the multithreaded parallel computation -for batches of detector pixels (`SimulationElement`s). It -- uses `ISimulation2D::generateSingleThreadedComputation` - to create instances of `DWBAComputation < IComputation`; -- for each instance, runs `IComputation.run`; -- calls `ISimulation2D::normalize`; -- calls `ISimulation2D::addBackgroundIntensity`. - -The `IComputation` constructor creates the member `up<ProcessedSample> m_processed_sample` - by calling the c'tor `ProcessedSample(sample, sim_options, forcePolarized)` - -The `DWBAComputation` constructor -populates the member `DWBASingleComputation m_single_computation`: -- For each `ProcessedLayout` in `m_processed_sample->layouts()`, - the vector `DWBASingleComputation::m_layout_comps` - is given a `new ParticleLayoutComputation` member; -- if `m_processed_sample->hasRoughness()`, - then `DWBASingleComputation::m_roughness_comp` - points to a `new RoughMultiLayerComputation`. - -`IComputation::run` calls `DWBAComputation::runProtected`, - which for each `SimulationElement` in the batch calls `m_single_computation.compute`. - -### Compute scattering as incoherent sum - -`DWBASingleComputation::compute(SimulationElement& ele)` -Computes Fresnel coefficients (`Fluxes`), - and transfers them to `ele`. - They will be used at the very end of the call following call chains - - in `ComputeDWBA::computeFF` for scattering from particles - -Then it performs an incoherent summation - by calling functions `compute(ele)` - that increment `ele.m_intensity`. -This is done -- from each `ProcessedLayout`, -- from each rough interface, -- from transmission(?) and specular reflection. - -### Scattering from a particle layout - -The `ParticleLayoutComputation` constructor -points the member `m_interference_function_strategy` - to a `new DecouplingApproximationStrategy`, -unless we are simulating a radial paracrystal, - for which the `SSCApproximationStrategy` is used. - -`ParticleLayoutComputation::compute` - increments `SimulationElement::m_intensity` - by a scattering intensity times the `ProcessedLayout::surfaceDensity()`. -The intensity is computed by `IInterferenceFunctionStrategy::evaluate`. -Except for Monte-Carlo integration, - this wraps just one call to `IInterferenceFunctionStrategy::evaluateSinglePoint`. -For unpolarized scattering, and except for radial paracrystals, - the next call goes to `DecouplingApproximationStrategy::scalarCalculation`. - -`DecouplingApproximationStrategy::scalarCalculation` - performs a coherent and an incoherent summation - over scattering amplitudes `ff` - obtained by calling `FormFactorCoherentSum::summedFF` - on members of `ProcessedLayout::formFactorList()`. -The mixed sum is sum - -> |ff|^2 + |sum ff|^2 * (coherence_factor - 1) - -where coherence_factor is computed by `IInterferenceFunction::evaluate`. - -Except for superlattices, there is no "inner" structure, -and therefore `IInterferenceFunction::evaluate` just wraps `IInterferenceFunction::iff_no_inner`, -so that - -> coherence_factor = DWfactor(q) * (iff_without_dw(q) * outer_iff - 1) + 1. - -By default, outer_iff = 1, so that - -> coherence_factor = DWfactor(q) * (iff_without_dw - 1) + 1. - -For the simplest of all interference functions, -`InterferenceFunctionNone::iff_without_dw` just returns 1, so that - -> coherence_factor = 1. - -### Computing the particle formfactor - -`FormFactorCoherentSum::summedFF` returns the sum over `FormFactorCoherentPart::coherentFF`. - -`FormFactorCoherentPart::coherentFF` makes use of `SimulationElement::fresnelMap` -to compute `in` and `out` coefficients. - -`FormFactorCoherentPart` wraps an `IComputeFF` and additionally holds -member `m_layer_index` -that is set by `FormFactorCoherentPart::setSpecularInfo`. -This information is forwarded by calling `IComputeFF::setSpecularInfo`, -which does nothing, unless overridden in `ComputeDWBA`. - -After this preparation, `ComputeDWBA::computeFF` -computes the coherent sum over the four DWBA terms. -Each of them uses the scattering amplitude from `IFormFactor::evaluate`, -which is pure virtual, overridden by `IFormFactorBorn::evaluate`, -which calls `IFormFactorBorn::evaluate_for_q`, -which is pure virtual, overriden by shape-specific classes like `FormFactorSphere`. -- GitLab