From 0f24409e9ad6d86f51425fb6fbfed81242cafef8 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Wed, 26 Feb 2020 17:41:23 +0100 Subject: [PATCH] - new frontend for MESA-PD - added ability to create custom modules --- python/mesa_pd.py | 239 ++++++++---------- python/mesa_pd/Container.py | 32 --- python/mesa_pd/Module.py | 60 +++++ python/mesa_pd/Property.py | 91 ------- python/mesa_pd/__init__.py | 3 + python/mesa_pd/accessor/Accessor.py | 75 ++---- python/mesa_pd/accessor/__init__.py | 4 +- python/mesa_pd/data/ContactHistory.py | 84 ++++-- python/mesa_pd/data/ContactStorage.py | 86 +++++-- python/mesa_pd/data/LinkedCells.py | 8 +- python/mesa_pd/data/ParticleStorage.py | 143 +++++++---- python/mesa_pd/data/ShapeStorage.py | 23 +- python/mesa_pd/data/SparseLinkedCells.py | 8 +- python/mesa_pd/data/__init__.py | 1 - .../mesa_pd/kernel/DetectAndStoreContacts.py | 31 +-- python/mesa_pd/kernel/DoubleCast.py | 23 +- python/mesa_pd/kernel/ExplicitEuler.py | 38 ++- .../mesa_pd/kernel/ExplicitEulerWithShape.py | 46 ++-- python/mesa_pd/kernel/ForceLJ.py | 36 ++- python/mesa_pd/kernel/HCSITSRelaxationStep.py | 71 +++--- python/mesa_pd/kernel/HeatConduction.py | 37 ++- .../mesa_pd/kernel/InitContactsForHCSITS.py | 64 +++-- .../mesa_pd/kernel/InitParticlesForHCSITS.py | 69 ++--- .../kernel/InsertParticleIntoLinkedCells.py | 26 +- .../InsertParticleIntoSparseLinkedCells.py | 26 +- .../kernel/IntegrateParticlesHCSITS.py | 67 +++-- python/mesa_pd/kernel/LinearSpringDashpot.py | 39 ++- .../mesa_pd/kernel/NonLinearSpringDashpot.py | 39 ++- python/mesa_pd/kernel/SingleCast.py | 26 +- python/mesa_pd/kernel/SpringDashpot.py | 46 ++-- .../mesa_pd/kernel/TemperatureIntegration.py | 37 ++- python/mesa_pd/kernel/VelocityVerlet.py | 44 ++-- .../mesa_pd/kernel/VelocityVerletWithShape.py | 67 ++--- python/mesa_pd/mpi/BroadcastProperty.py | 8 +- python/mesa_pd/mpi/ClearNextNeighborSync.py | 23 +- python/mesa_pd/mpi/Notifications.py | 22 ++ python/mesa_pd/mpi/ReduceContactHistory.py | 8 +- python/mesa_pd/mpi/ReduceProperty.py | 8 +- python/mesa_pd/mpi/ShapePackUnpack.py | 15 +- python/mesa_pd/mpi/SyncGhostOwners.py | 28 +- python/mesa_pd/mpi/SyncNextNeighbors.py | 27 +- .../mesa_pd/mpi/SyncNextNeighborsNoGhosts.py | 14 + python/mesa_pd/mpi/__init__.py | 3 + .../templates/data/ShapeStorage.templ.h | 12 +- .../templates/kernel/DoubleCast.templ.h | 6 +- .../templates/kernel/SingleCast.templ.h | 4 +- .../templates/mpi/ShapePackUnpack.templ.h | 4 +- .../mpi/SyncNextNeighborsNoGhosts.templ.cpp | 162 ++++++++++++ .../mpi/SyncNextNeighborsNoGhosts.templ.h | 81 ++++++ .../mpi/notifications/ParseMessage.templ.h | 4 +- .../ParticleCopyNotification.templ.h | 8 +- .../ParticleGhostCopyNotification.templ.h | 8 +- .../ParticleMigrationNotification.templ.h | 6 +- .../ParticleUpdateNotification.templ.h | 6 +- python/mesa_pd/utility.py | 68 +++-- src/mesa_pd/data/ParticleAccessor.h | 72 +++--- src/mesa_pd/data/ParticleStorage.h | 232 ++++++++--------- src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp | 162 ++++++++++++ src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h | 81 ++++++ src/mesa_pd/mpi/notifications/ParseMessage.h | 2 +- .../notifications/ParticleCopyNotification.h | 24 +- .../ParticleGhostCopyNotification.h | 16 +- .../ParticleUpdateNotification.h | 6 +- tests/mesa_pd/CMakeLists.txt | 3 + .../mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp | 90 +++++++ 65 files changed, 1780 insertions(+), 1122 deletions(-) delete mode 100644 python/mesa_pd/Container.py create mode 100644 python/mesa_pd/Module.py delete mode 100644 python/mesa_pd/Property.py create mode 100644 python/mesa_pd/mpi/Notifications.py create mode 100644 python/mesa_pd/mpi/SyncNextNeighborsNoGhosts.py create mode 100644 python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp create mode 100644 python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h create mode 100644 src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp create mode 100644 src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h create mode 100644 tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp diff --git a/python/mesa_pd.py b/python/mesa_pd.py index 17c03fb8d..b567d0876 100755 --- a/python/mesa_pd.py +++ b/python/mesa_pd.py @@ -1,7 +1,7 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor +from mesa_pd import Module import mesa_pd.data as data import mesa_pd.kernel as kernel import mesa_pd.mpi as mpi @@ -11,136 +11,107 @@ import numpy as np import os if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Generate all necessary files for the waLBerla mesa_pd module.') - parser.add_argument('path', help='Where should the files be created?') - parser.add_argument("-f", "--force", help="Generate the files even if not inside a waLBerla directory.", - action="store_true") - args = parser.parse_args() - - if ((not os.path.isfile(args.path + "/src/walberla.h")) and (not args.force)): - raise RuntimeError(args.path + " is not the path to a waLBerla root directory! Specify -f to generate the files anyway.") - - os.makedirs(args.path + "/src/mesa_pd/common", exist_ok = True) - os.makedirs(args.path + "/src/mesa_pd/data", exist_ok = True) - os.makedirs(args.path + "/src/mesa_pd/domain", exist_ok = True) - os.makedirs(args.path + "/src/mesa_pd/kernel", exist_ok = True) - os.makedirs(args.path + "/src/mesa_pd/mpi/notifications", exist_ok = True) - os.makedirs(args.path + "/src/mesa_pd/vtk", exist_ok = True) - - shapes = ["Sphere", "HalfSpace", "CylindricalBoundary", "Box", "Ellipsoid"] - - ps = data.ParticleStorage() - ch = data.ContactHistory() - lc = data.LinkedCells() - slc = data.SparseLinkedCells() - ss = data.ShapeStorage(ps, shapes) - cs = data.ContactStorage() - - ps.addProperty("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") - ps.addProperty("linearVelocity", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") - ps.addProperty("invMass", "walberla::real_t", defValue="real_t(1)", syncMode="ON_GHOST_CREATION") - ps.addProperty("force", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - ps.addProperty("oldForce", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ON_OWNERSHIP_CHANGE") - - ps.addProperty("shapeID", "size_t", defValue="", syncMode="ON_GHOST_CREATION") - ps.addProperty("rotation", "walberla::mesa_pd::Rot3", defValue="", syncMode="ALWAYS") - ps.addProperty("angularVelocity", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") - ps.addProperty("torque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - ps.addProperty("oldTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ON_OWNERSHIP_CHANGE") - - ps.addInclude("blockforest/BlockForest.h") - ps.addProperty("currentBlock", "blockforest::BlockID", defValue="", syncMode="NEVER") - - ps.addProperty("type", "uint_t", defValue="0", syncMode="ON_GHOST_CREATION") - - ps.addProperty("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", syncMode="ON_GHOST_CREATION") - ps.addProperty("nextParticle", "int", defValue="-1", syncMode="NEVER") - - ps.addProperty("oldContactHistory", "std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory>", defValue="", syncMode="ALWAYS") - ps.addProperty("newContactHistory", "std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory>", defValue="", syncMode="NEVER") - - ps.addProperty("temperature", "walberla::real_t", defValue="real_t(0)", syncMode="ALWAYS") - ps.addProperty("heatFlux", "walberla::real_t", defValue="real_t(0)", syncMode="NEVER") - - # Properties for HCSITS - ps.addProperty("dv", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - ps.addProperty("dw", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - - # Properties for lbm_mesapd_coupling: - ps.addProperty("hydrodynamicForce", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - ps.addProperty("hydrodynamicTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - ps.addProperty("oldHydrodynamicForce", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - ps.addProperty("oldHydrodynamicTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - - - ch.addProperty("tangentialSpringDisplacement", "walberla::mesa_pd::Vec3", defValue="real_t(0)") - ch.addProperty("isSticking", "bool", defValue="false") - ch.addProperty("impactVelocityMagnitude", "real_t", defValue="real_t(0)") - - cs.addProperty("id1", "walberla::id_t", defValue = "walberla::id_t(-1)", syncMode="NEVER") - cs.addProperty("id2", "walberla::id_t", defValue = "walberla::id_t(-1)", syncMode="NEVER") - cs.addProperty("distance", "real_t", defValue = "real_t(1)", syncMode="NEVER") - cs.addProperty("normal", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("position", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("t", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("o", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("r1", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("r2", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("mu", "real_t", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("p", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("diag_nto", "walberla::mesa_pd::Mat3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("diag_nto_inv", "walberla::mesa_pd::Mat3", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("diag_to_inv", "walberla::mesa_pd::Mat2", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("diag_n_inv", "real_t", defValue = "real_t(0)", syncMode="NEVER") - cs.addProperty("p", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="NEVER") - - - kernels = [] - kernels.append( kernel.DetectAndStoreContacts() ) - kernels.append( kernel.DoubleCast(shapes) ) - kernels.append( kernel.ExplicitEuler() ) - kernels.append( kernel.ExplicitEulerWithShape() ) - kernels.append( kernel.ForceLJ() ) - kernels.append( kernel.HCSITSRelaxationStep() ) - kernels.append( kernel.HeatConduction() ) - kernels.append( kernel.InitParticlesForHCSITS() ) - kernels.append( kernel.InitContactsForHCSITS() ) - kernels.append( kernel.IntegrateParticlesHCSITS() ) - kernels.append( kernel.InsertParticleIntoLinkedCells() ) - kernels.append( kernel.InsertParticleIntoSparseLinkedCells() ) - kernels.append( kernel.LinearSpringDashpot() ) - kernels.append( kernel.NonLinearSpringDashpot() ) - kernels.append( kernel.SingleCast(shapes) ) - kernels.append( kernel.SpringDashpot() ) - kernels.append( kernel.TemperatureIntegration() ) - kernels.append( kernel.VelocityVerlet() ) - kernels.append( kernel.VelocityVerletWithShape() ) - - - ac = Accessor() - for k in kernels: - ac.mergeRequirements(k.getRequirements()) - ac.printSummary() - - comm = [] - comm.append(mpi.BroadcastProperty()) - comm.append(mpi.ClearNextNeighborSync()) - comm.append(mpi.ReduceContactHistory()) - comm.append(mpi.ReduceProperty()) - comm.append(mpi.ShapePackUnpack(shapes)) - comm.append(mpi.SyncGhostOwners(ps)) - comm.append(mpi.SyncNextNeighbors(ps)) - - - ps.generate(args.path + "/src/mesa_pd/") - ch.generate(args.path + "/src/mesa_pd/") - lc.generate(args.path + "/src/mesa_pd/") - slc.generate(args.path + "/src/mesa_pd/") - ss.generate(args.path + "/src/mesa_pd/") - cs.generate(args.path + "/src/mesa_pd/") - - for k in kernels: - k.generate(args.path + "/src/mesa_pd/") - - for c in comm: - c.generate(args.path + "/src/mesa_pd/") + parser = argparse.ArgumentParser(description='Generate all necessary files for the waLBerla mesa_pd module.') + parser.add_argument('path', help='Where should the files be created?') + args = parser.parse_args() + + mpd = Module(args.path) + ps = mpd.add(data.ParticleStorage()) + ps.set_shapes('Sphere', 'HalfSpace', 'CylindricalBoundary', 'Box', 'Ellipsoid') + ps.add_property("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + ps.add_property("linearVelocity", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + ps.add_property("invMass", "walberla::real_t", defValue="real_t(1)", syncMode="ON_GHOST_CREATION") + ps.add_property("force", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + ps.add_property("oldForce", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ON_OWNERSHIP_CHANGE") + + ps.add_property("shapeID", "size_t", defValue="", syncMode="ON_GHOST_CREATION") + ps.add_property("rotation", "walberla::mesa_pd::Rot3", defValue="", syncMode="ALWAYS") + ps.add_property("angularVelocity", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + ps.add_property("torque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + ps.add_property("oldTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ON_OWNERSHIP_CHANGE") + + ps.add_include("blockforest/BlockForest.h") + ps.add_property("currentBlock", "blockforest::BlockID", defValue="", syncMode="NEVER") + + ps.add_property("type", "uint_t", defValue="0", syncMode="ON_GHOST_CREATION") + + ps.add_property("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", + syncMode="ON_GHOST_CREATION") + ps.add_property("nextParticle", "int", defValue="-1", syncMode="NEVER") + + ps.add_property("oldContactHistory", "std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory>", + defValue="", syncMode="ALWAYS") + ps.add_property("newContactHistory", "std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory>", + defValue="", syncMode="NEVER") + + ps.add_property("temperature", "walberla::real_t", defValue="real_t(0)", syncMode="ALWAYS") + ps.add_property("heatFlux", "walberla::real_t", defValue="real_t(0)", syncMode="NEVER") + + # Properties for HCSITS + ps.add_property("dv", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + ps.add_property("dw", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + + # Properties for lbm_mesapd_coupling: + ps.add_property("hydrodynamicForce", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + ps.add_property("hydrodynamicTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + ps.add_property("oldHydrodynamicForce", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + ps.add_property("oldHydrodynamicTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + + ch = mpd.add(data.ContactHistory()) + ch.add_property("tangentialSpringDisplacement", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + ch.add_property("isSticking", "bool", defValue="false") + ch.add_property("impactVelocityMagnitude", "real_t", defValue="real_t(0)") + + cs = mpd.add(data.ContactStorage()) + cs.add_property("id1", "walberla::id_t", defValue="walberla::id_t(-1)") + cs.add_property("id2", "walberla::id_t", defValue="walberla::id_t(-1)") + cs.add_property("distance", "real_t", defValue="real_t(1)") + cs.add_property("normal", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("t", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("o", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("r1", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("r2", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("mu", "real_t", defValue="real_t(0)") + cs.add_property("p", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + cs.add_property("diag_nto", "walberla::mesa_pd::Mat3", defValue="real_t(0)") + cs.add_property("diag_nto_inv", "walberla::mesa_pd::Mat3", defValue="real_t(0)") + cs.add_property("diag_to_inv", "walberla::mesa_pd::Mat2", defValue="real_t(0)") + cs.add_property("diag_n_inv", "real_t", defValue="real_t(0)") + cs.add_property("p", "walberla::mesa_pd::Vec3", defValue="real_t(0)") + + mpd.add(data.LinkedCells()) + mpd.add(data.SparseLinkedCells()) + mpd.add(data.ShapeStorage(ps)) + + mpd.add(kernel.DetectAndStoreContacts()) + mpd.add(kernel.DoubleCast(ps)) + mpd.add(kernel.ExplicitEuler()) + mpd.add(kernel.ExplicitEulerWithShape()) + mpd.add(kernel.ForceLJ()) + mpd.add(kernel.HCSITSRelaxationStep()) + mpd.add(kernel.HeatConduction()) + mpd.add(kernel.InitParticlesForHCSITS()) + mpd.add(kernel.InitContactsForHCSITS()) + mpd.add(kernel.IntegrateParticlesHCSITS()) + mpd.add(kernel.InsertParticleIntoLinkedCells()) + mpd.add(kernel.InsertParticleIntoSparseLinkedCells()) + mpd.add(kernel.LinearSpringDashpot()) + mpd.add(kernel.NonLinearSpringDashpot()) + mpd.add(kernel.SingleCast(ps)) + mpd.add(kernel.SpringDashpot()) + mpd.add(kernel.TemperatureIntegration()) + mpd.add(kernel.VelocityVerlet()) + mpd.add(kernel.VelocityVerletWithShape()) + + mpd.add(mpi.BroadcastProperty()) + mpd.add(mpi.ClearNextNeighborSync()) + mpd.add(mpi.Notifications(ps)) + mpd.add(mpi.ReduceContactHistory()) + mpd.add(mpi.ReduceProperty()) + mpd.add(mpi.ShapePackUnpack(ps)) + mpd.add(mpi.SyncGhostOwners(ps)) + mpd.add(mpi.SyncNextNeighbors(ps)) + mpd.add(mpi.SyncNextNeighborsNoGhosts(ps)) + + mpd.generate() diff --git a/python/mesa_pd/Container.py b/python/mesa_pd/Container.py deleted file mode 100644 index 3acd960e6..000000000 --- a/python/mesa_pd/Container.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- - -from .Property import Property, unrollDimension -from .utility import find, TerminalColor - -class Container: - def __init__(self): - """Base class for a container which manages includes and properties - """ - - self.properties = [] - self.includes = [] - - def addProperty(self, name, type, access="grs", defValue="", syncMode = "ALWAYS", dim=1): - prop = find( lambda x : x.name == name, self.properties ) - if (prop == None): - #print(TerminalColor.GREEN + "creating particle property: {}".format(name) + TerminalColor.DEFAULT) - self.properties.append( Property(name, type, access=access, defValue=defValue, syncMode=syncMode, dim=dim) ) - else: - if not (prop.type == type and prop.name == name and prop.defValue == defValue and prop.dim == dim): - raise RuntimeError(TerminalColor.RED + "property definition differs from previous one:\nPREVIOUS {}\nNEW {}".format(prop, Property(name, type, defValue=defValue, syncMode=syncMode, dim=dim)) + TerminalColor.DEFAULT) - print(TerminalColor.YELLOW + "reusing particle property: {}".format(name) + TerminalColor.DEFAULT) - - def addInclude(self, include): - if (include in self.includes): - print(TerminalColor.YELLOW + "reusing particle include: {}".format(include) + TerminalColor.DEFAULT) - else: - #print(TerminalColor.GREEN + "creating particle include: {}".format(include) + TerminalColor.DEFAULT) - self.includes.append(include) - - def unrollDimension(self): - self.properties = unrollDimension(self.properties) diff --git a/python/mesa_pd/Module.py b/python/mesa_pd/Module.py new file mode 100644 index 000000000..dc94b5fbf --- /dev/null +++ b/python/mesa_pd/Module.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +from pathlib import Path +import shutil +import os + + +class Module: + def __init__(self, path, module_name='mesa_pd'): + """Propery of a data strcuture + + Parameters + ---------- + path : str + path to the root waLBerla folder + module_name : str + name of the generated module + """ + + self.context = {} + self.context['path'] = Path(path).resolve() + self.context['name'] = module_name + self.context['module_path'] = self.context['path'] / 'src' / self.context['name'] + self.context['test_path'] = self.context['path'] / 'tests' / self.context['name'] + + self.components = [] + + def add(self, component): + self.components.append(component) + return component + + def rename(self): + for root, dirnames, filenames in os.walk(self.context['module_path']): + for filename in filenames: + filedata = None + print(f'{root}/{filename}') + with open(f'{root}/{filename}', 'r') as file: + filedata = file.read() + + filedata = filedata.replace('mesa_pd', self.context['name']) + + with open(f'{root}/{filename}', 'w') as file: + file.write(filedata) + + def generate(self, folder_check=True): + if (folder_check): + print(f"This operation will overwrite the content of: {self.context['module_path']}") + answer = input("Continue? (y to confirm)") + if (answer != "y"): + return + + mesa_pd_folder = (Path(__file__).parents[2] / 'src' / 'mesa_pd').resolve() + if (mesa_pd_folder != self.context['module_path']): + shutil.rmtree(self.context['module_path']) + shutil.copytree(mesa_pd_folder, self.context['module_path']) + + for d in self.components: + d.generate(self.context) + + self.rename() \ No newline at end of file diff --git a/python/mesa_pd/Property.py b/python/mesa_pd/Property.py deleted file mode 100644 index d0da37d9f..000000000 --- a/python/mesa_pd/Property.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- - -from .utility import TerminalColor - -class Property: - def __init__(self, name, type, access="grs", defValue="", syncMode = "ALWAYS", dim=1): - """Propery of a data strcuture - - Parameters - ---------- - name : str - name of the property - type : str - type of the property - access : str - 'g' for getter (getName) - 'r' for reference (getNameRef) - 's' for setter (setName) - any combination is possible - defValue : str - default value the property should be initialized with - syncMode : str - 'NEVER', this property does not have to be synced - 'ON_GHOST_CREATION', this property must be synced on creation - 'ON_OWNERSHIP_CHANGE', this property must be synced when the ownership changes - 'ALWAYS', this property has to be synced in every iteration - dim : int - dimensions of the property - """ - - #sort access specifier and remove duplicates - foo = "".join(sorted(access)) - access = ''.join([foo[i] for i in range(len(foo)-1) if foo[i+1]!= foo[i]]+[foo[-1]]) - - for acc in access: - if not (acc in ["g","s","r"]): - raise RuntimeError("{} is not a valid access specifier in {}".format(acc, access)) - - if (not syncMode in ["NEVER", "ON_GHOST_CREATION", "ON_OWNERSHIP_CHANGE", "ALWAYS"]): - raise RuntimeError(TerminalColor.RED + "{} is no valid sync for property: {}".format(syncMode, name) + TerminalColor.DEFAULT) - - if (dim < 1): - raise RuntimeError(TerminalColor.RED + "dimension has to be >=1: {}".format(dim) + TerminalColor.DEFAULT) - - self.name = name - self.type = type - self.access = access - self.defValue = defValue - self.syncMode = syncMode - self.dim = dim - - def __str__(self): - return "name: {}, type: {}, access: {}, defValue: {}, syncMode: {}, dim: {}".format(self.name, self.type, self.access, self.defValue, self.syncMode, self.dim) - - def getAccessFunction(self): - """Returns a list of accessor function names - """ - - funcs = [] - if 'g' in self.access: - funcs.append("get" + self.name.capitalize()) - if 's' in self.access: - funcs.append("set" + self.name.capitalize()) - if 'r' in self.access: - funcs.append("get" + self.name.capitalize() + "Ref") - return funcs - -def unrollDimension(props): - """Unrolls all more dimensional properties into one dimensional properties - - Iterates over all elements. Copies all one dimensional properties. - More dimensional properties get split into one dimensional properties with added suffix. - - Parameters - ---------- - props : list - list of properties to be unrolled - - Returns - ------- - list of unrolled properties - """ - - unrolled = [] - for prop in props: - if (prop.dim == 1): - unrolled.append(Property(prop.name, prop.type, prop.access, prop.defValue, prop.syncMode, prop.dim)) - else: - for d in range(prop.dim): - unrolled.append(Property("{}{}".format(prop.name,d), prop.type, prop.access, prop.defValue, prop.syncMode, 1)) - return unrolled diff --git a/python/mesa_pd/__init__.py b/python/mesa_pd/__init__.py index e69de29bb..d68cd8086 100644 --- a/python/mesa_pd/__init__.py +++ b/python/mesa_pd/__init__.py @@ -0,0 +1,3 @@ +from .Module import Module + +__all__ = ['Module'] \ No newline at end of file diff --git a/python/mesa_pd/accessor/Accessor.py b/python/mesa_pd/accessor/Accessor.py index 288ff22e4..88c081895 100644 --- a/python/mesa_pd/accessor/Accessor.py +++ b/python/mesa_pd/accessor/Accessor.py @@ -1,53 +1,28 @@ # -*- coding: utf-8 -*- -from ..Property import Property -from ..utility import find, TerminalColor, generateFile -class Accessor: - def __init__(self): - self.properties = [] - - def require(self, name, type, access): - """requires that a certain property is accessible - - Parameters - ---------- - name : str - name of the property requested - type : str - type of the requested property - access : str - 'g' for getter (getName) - 'r' for reference (getNameRef) - 's' for setter (setName) - any combination is possible - - Example - ------- - require("position", "walberla::mesa_pd::Vec3", "sg") - """ - - prop = find( lambda x : x.name == name, self.properties ) - if (prop == None): - #print(TerminalColor.GREEN + "[{}] creating particle property: {}".format(info, name) + TerminalColor.DEFAULT) - self.properties.append( Property(name, type, access = access) ) - else: - if not (prop.type == type): - raise RuntimeError(TerminalColor.RED + "requirement definition differs from previous one:\n{} {}\n{} {}".format(name, type, prop.name, prop.type) + TerminalColor.DEFAULT) - foo = "".join(sorted(access + prop.access)) - prop.access = ''.join([foo[i] for i in range(len(foo)-1) if foo[i+1]!= foo[i]]+[foo[-1]]) - - - def mergeRequirements(self, accessor): - for req in accessor.properties: - self.require( req.name, req.type, req.access ) - - def printSummary(self): - print("="*90) - print("Requirements for Accessor:") - print("") - print("{0: <30}{1: <30}{2: <30}".format("Name", "Type", "Access")) - print("="*90) - for gs in self.properties: - print("{0: <30.29}{1: <30.29}{2: <30.29}".format(gs.name, gs.type, gs.access)) - print("="*90) +def create_access(name, type, access): + """requires that a certain property is accessible + + Parameters + ---------- + name : str + name of the property requested + type : str + type of the requested property + access : str + 'g' for getter (getName) + 'r' for reference (getNameRef) + 's' for setter (setName) + any combination is possible + + Example + ------- + create_access("position", "walberla::mesa_pd::Vec3", "sg") + """ + + for acc in access: + if not (acc in ["g", "s", "r"]): + raise RuntimeError(f"{acc} is not a valid access specifier in {access}") + + return {'name': name, 'type': type, 'access': access} diff --git a/python/mesa_pd/accessor/__init__.py b/python/mesa_pd/accessor/__init__.py index 6e15afb2c..1d37a364c 100644 --- a/python/mesa_pd/accessor/__init__.py +++ b/python/mesa_pd/accessor/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from .Accessor import Accessor +from .Accessor import create_access -__all__ = ['Accessor'] +__all__ = ['create_access'] diff --git a/python/mesa_pd/data/ContactHistory.py b/python/mesa_pd/data/ContactHistory.py index 444da6bfc..08e80a6f4 100644 --- a/python/mesa_pd/data/ContactHistory.py +++ b/python/mesa_pd/data/ContactHistory.py @@ -1,28 +1,62 @@ # -*- coding: utf-8 -*- import numpy as np -from ..Container import Container -from ..utility import generateFile - -class ContactHistory(Container): - def __init__(self): - super().__init__() - - def generate(self, path): - self.unrollDimension() - - print("="*90) - print("Creating ContactHistory Datastructure:") - print("") - print("{0: <20}{1: <30}{2: <20}{3: <10}".format("Type", "Name", "Def. Value", "SyncMode")) - print("="*90) - for prop in self.properties: - print("{0: <20.19}{1: <30.29}{2: <20.19}{3: <10.9}".format(prop.type, prop.name, prop.defValue, prop.syncMode)) - print("="*90) - - context = dict() - context["includes"] = self.includes - context["properties"] = self.properties - - generateFile(path, 'data/ContactHistory.templ.h', context, filename='data/ContactHistory.h') - generateFile(path, 'mpi/notifications/ContactHistoryNotification.templ.h', context) +from ..utility import TerminalColor, find, generate_file + + +def create_contact_history_property(name, type, defValue=""): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + """ + + return {'name': name, 'type': type, 'defValue': defValue} + + +class ContactHistory(): + def __init__(self): + self.context = {'includes': [], 'properties': []} + + def add_property(self, name, type, defValue=""): + prop = find(lambda x: x['name'] == name, self.context['properties']) + if (prop == None): + # print(f"{TerminalColor.GREEN} creating property: {name} {TerminalColor.DEFAULT}") + self.context['properties'].append(create_contact_history_property(name, type, defValue=defValue)) + else: + if not (prop['type'] == type and prop['name'] == name and prop['defValue'] == defValue): + new_prop = create_contact_history_property(name, type, defValue=defValue) + raise RuntimeError( + f"{TerminalColor.RED} property definition differs from previous one:\nPREVIOUS {prop}\nNEW {new_prop} {TerminalColor.DEFAULT}") + print(f"{TerminalColor.YELLOW} reusing property: {name} {TerminalColor.DEFAULT}") + + def add_include(self, include): + if (include in self.context['includes']): + print(f"{TerminalColor.YELLOW} reusing include: {include} {TerminalColor.DEFAULT}") + else: + # print(f"{TerminalColor.GREEN} creating include: {include} {TerminalColor.DEFAULT}") + self.context['includes'].append(include) + + def print(self): + print("=" * 90) + print("Creating ContactHistory Datastructure:") + print("") + print("{0: <20}{1: <30}{2: <20}{3: <10}".format("Type", "Name", "Def. Value", "SyncMode")) + print("=" * 90) + for prop in self.properties: + print("{0: <20.19}{1: <30.29}{2: <20.19}{3: <10.9}".format(prop.type, prop.name, prop.defValue, + prop.syncMode)) + print("=" * 90) + + def generate(self, module): + ctx = {} + ctx['module'] = module + ctx.update(self.context) + + generate_file(module['module_path'], 'data/ContactHistory.templ.h', ctx, filename='data/ContactHistory.h') + generate_file(module['module_path'], 'mpi/notifications/ContactHistoryNotification.templ.h', ctx) diff --git a/python/mesa_pd/data/ContactStorage.py b/python/mesa_pd/data/ContactStorage.py index 210675931..9dd669381 100644 --- a/python/mesa_pd/data/ContactStorage.py +++ b/python/mesa_pd/data/ContactStorage.py @@ -1,29 +1,63 @@ # -*- coding: utf-8 -*- import numpy as np -from ..Container import Container -from ..utility import generateFile - -class ContactStorage(Container): - def __init__(self): - super().__init__() - self.addProperty("uid", "walberla::id_t", defValue = "walberla::id_t(-1)", syncMode="NEVER") - - def generate(self, path): - self.unrollDimension() - - print("="*90) - print("Creating ContactStorage Datastructure:") - print("") - print("{0: <20}{1: <30}{2: <20}{3: <10}".format("Type", "Name", "Def. Value", "SyncMode")) - print("="*90) - for prop in self.properties: - print("{0: <20.19}{1: <30.29}{2: <20.19}{3: <10.9}".format(prop.type, prop.name, prop.defValue, prop.syncMode)) - print("="*90) - - context = dict() - context["includes"] = self.includes - context["properties"] = self.properties - - generateFile(path, 'data/ContactStorage.templ.h', context, filename='data/ContactStorage.h') - generateFile(path, 'data/ContactAccessor.templ.h', context, filename='data/ContactAccessor.h') +from ..utility import TerminalColor, find, generate_file + + +def create_contact_storage_property(name, type, defValue=""): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + """ + + return {'name': name, 'type': type, 'defValue': defValue} + + +class ContactStorage(): + def __init__(self): + self.context = {'includes': [], 'properties': []} + self.add_property("uid", "walberla::id_t", defValue="walberla::id_t(-1)") + + def add_property(self, name, type, defValue=""): + prop = find(lambda x: x['name'] == name, self.context['properties']) + if (prop == None): + # print(f"{TerminalColor.GREEN} creating property: {name} {TerminalColor.DEFAULT}") + self.context['properties'].append(create_contact_storage_property(name, type, defValue=defValue)) + else: + if not (prop['type'] == type and prop['name'] == name and prop['defValue'] == defValue): + new_prop = create_contact_storage_property(name, type, defValue=defValue) + raise RuntimeError( + f"{TerminalColor.RED} property definition differs from previous one:\nPREVIOUS {prop}\nNEW {new_prop} {TerminalColor.DEFAULT}") + print(f"{TerminalColor.YELLOW} reusing property: {name} {TerminalColor.DEFAULT}") + + def add_include(self, include): + if (include in self.context['includes']): + print(f"{TerminalColor.YELLOW} reusing include: {include} {TerminalColor.DEFAULT}") + else: + # print(f"{TerminalColor.GREEN} creating include: {include} {TerminalColor.DEFAULT}") + self.context['includes'].append(include) + + def print(self): + print("=" * 90) + print("Creating ContactStorage Datastructure:") + print("") + print("{0: <20}{1: <30}{2: <20}{3: <10}".format("Type", "Name", "Def. Value", "SyncMode")) + print("=" * 90) + for prop in self.properties: + print("{0: <20.19}{1: <30.29}{2: <20.19}{3: <10.9}".format(prop.type, prop.name, prop.defValue, + prop.syncMode)) + print("=" * 90) + + def generate(self, module): + ctx = {} + ctx['module'] = module + ctx.update(self.context) + + generate_file(module['module_path'], 'data/ContactStorage.templ.h', ctx, filename='data/ContactStorage.h') + generate_file(module['module_path'], 'data/ContactAccessor.templ.h', ctx, filename='data/ContactAccessor.h') diff --git a/python/mesa_pd/data/LinkedCells.py b/python/mesa_pd/data/LinkedCells.py index 60ea2ec83..5ff4c9b8d 100644 --- a/python/mesa_pd/data/LinkedCells.py +++ b/python/mesa_pd/data/LinkedCells.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- import numpy as np -from ..utility import generateFile +from ..utility import generate_file + class LinkedCells: - def generate(self, path): - generateFile(path, 'data/LinkedCells.templ.h') + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'data/LinkedCells.templ.h', ctx) diff --git a/python/mesa_pd/data/ParticleStorage.py b/python/mesa_pd/data/ParticleStorage.py index 7f9813a06..61264f240 100644 --- a/python/mesa_pd/data/ParticleStorage.py +++ b/python/mesa_pd/data/ParticleStorage.py @@ -1,49 +1,100 @@ # -*- coding: utf-8 -*- import numpy as np -from ..Container import Container -from ..utility import generateFile - -class ParticleStorage(Container): - def __init__(self): - super().__init__() - - self.addInclude("mesa_pd/data/Flags.h") - - self.addProperty("uid", "walberla::id_t", defValue = "UniqueID<data::Particle>::invalidID()", syncMode="ALWAYS") - self.addProperty("position", "walberla::mesa_pd::Vec3", defValue = "real_t(0)", syncMode="ALWAYS") - self.addProperty("interactionRadius", "walberla::real_t", defValue = "real_t(0)", syncMode="ON_GHOST_CREATION") - self.addProperty("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue = "", syncMode="ON_GHOST_CREATION") - self.addProperty("owner", "int", defValue = "-1", syncMode="ON_GHOST_CREATION") - self.addProperty("ghostOwners", "std::unordered_set<walberla::mpi::MPIRank>", defValue = "", syncMode="ON_OWNERSHIP_CHANGE") - - def generate(self, path): - self.unrollDimension() - - print("="*90) - print("Creating Particle Datastructure:") - print("") - print("{0: <20}{1: <30}{2: <20}{3: <10}".format("Type", "Name", "Def. Value", "SyncMode")) - print("="*90) - for prop in self.properties: - print("{0: <20.19}{1: <30.29}{2: <20.19}{3: <10.9}".format(prop.type, prop.name, prop.defValue, prop.syncMode)) - print("="*90) - - context = dict() - context["includes"] = self.includes - context["properties"] = self.properties - - generateFile(path, 'data/ParticleStorage.templ.h', context, filename='data/ParticleStorage.h') - generateFile(path, 'data/ParticleAccessor.templ.h', context, filename='data/ParticleAccessor.h') - - generateFile(path, 'mpi/notifications/ForceTorqueNotification.templ.h', context) - generateFile(path, 'mpi/notifications/HeatFluxNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParseMessage.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleCopyNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleGhostCopyNotification.templ.h', context) - generateFile(path, 'mpi/notifications/NewGhostParticleNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleMigrationNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleRemoteMigrationNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleRemovalInformationNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleRemovalNotification.templ.h', context) - generateFile(path, 'mpi/notifications/ParticleUpdateNotification.templ.h', context) +from ..utility import find, TerminalColor, generate_file + + +def create_particle_property(name, type, access="grs", defValue="", syncMode="ALWAYS"): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + access : str + 'g' for getter (getName) + 'r' for reference (getNameRef) + 's' for setter (setName) + any combination is possible + defValue : str + default value the property should be initialized with + syncMode : str + 'NEVER', this property does not have to be synced + 'ON_GHOST_CREATION', this property must be synced on creation + 'ON_OWNERSHIP_CHANGE', this property must be synced when the ownership changes + 'ALWAYS', this property has to be synced in every iteration + """ + + # sort access specifier and remove duplicates + foo = "".join(sorted(access)) + access = ''.join([foo[i] for i in range(len(foo) - 1) if foo[i + 1] != foo[i]] + [foo[-1]]) + + for acc in access: + if not (acc in ["g", "s", "r"]): + raise RuntimeError(f"{acc} is not a valid access specifier in {access}") + + if (syncMode not in ["NEVER", "ON_GHOST_CREATION", "ON_OWNERSHIP_CHANGE", "ALWAYS"]): + raise RuntimeError( + f"{TerminalColor.RED}{syncMode} is no valid sync for property: {name}{TerminalColor.DEFAULT}") + + return {'name': name, 'type': type, 'access': access, 'defValue': defValue, 'syncMode': syncMode} + + +class ParticleStorage(): + def __init__(self): + self.context = {'includes': [], 'properties': []} + + self.add_include("mesa_pd/data/Flags.h") + + self.add_property("uid", "walberla::id_t", defValue="UniqueID<data::Particle>::invalidID()", syncMode="ALWAYS") + self.add_property("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + self.add_property("interactionRadius", "walberla::real_t", defValue="real_t(0)", syncMode="ON_GHOST_CREATION") + self.add_property("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", + syncMode="ON_GHOST_CREATION") + self.add_property("owner", "int", defValue="-1", syncMode="ON_GHOST_CREATION") + self.add_property("ghostOwners", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", + syncMode="ON_OWNERSHIP_CHANGE") + + def set_shapes(self, *shapes): + self.context['shapes'] = list(shapes) + + def add_property(self, name, type, access="grs", defValue="", syncMode="ALWAYS"): + prop = find(lambda x: x['name'] == name, self.context['properties']) + if (prop == None): + # print(f"{TerminalColor.GREEN} creating particle property: {name} {TerminalColor.DEFAULT}") + self.context['properties'].append( + create_particle_property(name, type, access=access, defValue=defValue, syncMode=syncMode)) + else: + if not (prop['type'] == type and prop['name'] == name and prop['defValue'] == defValue): + new_prop = create_particle_property(name, type, defValue=defValue, syncMode=syncMode) + raise RuntimeError( + f"{TerminalColor.RED} property definition differs from previous one:\nPREVIOUS {prop}\nNEW {new_prop} {TerminalColor.DEFAULT}") + print(f"{TerminalColor.YELLOW} reusing particle property: {name} {TerminalColor.DEFAULT}") + + def add_include(self, include): + if (include in self.context['includes']): + print(f"{TerminalColor.YELLOW} reusing particle include: {include} {TerminalColor.DEFAULT}") + else: + # print(f"{TerminalColor.GREEN} creating particle include: {include} {TerminalColor.DEFAULT}") + self.context['includes'].append(include) + + def print(self): + print("=" * 90) + print("Creating Particle Datastructure:") + print("") + print("{0: <20}{1: <30}{2: <20}{3: <10}".format("Type", "Name", "Def. Value", "SyncMode")) + print("=" * 90) + for prop in self.context['properties']: + print("{0: <20.19}{1: <30.29}{2: <20.19}{3: <10.9}".format(prop['type'], prop['name'], prop['defValue'], + prop['syncMode'])) + print("=" * 90) + + def get_context(self): + return self.context + + def generate(self, module): + ctx = {'module': module, **self.context} + + generate_file(module['module_path'], 'data/ParticleStorage.templ.h', ctx, filename='data/ParticleStorage.h') + generate_file(module['module_path'], 'data/ParticleAccessor.templ.h', ctx, filename='data/ParticleAccessor.h') diff --git a/python/mesa_pd/data/ShapeStorage.py b/python/mesa_pd/data/ShapeStorage.py index 74b4f598e..512cb2b29 100644 --- a/python/mesa_pd/data/ShapeStorage.py +++ b/python/mesa_pd/data/ShapeStorage.py @@ -1,19 +1,20 @@ # -*- coding: utf-8 -*- import numpy as np -from ..utility import generateFile +from ..utility import generate_file + class ShapeStorage: - def __init__(self, p, shapes): - p.addProperty("shapeID", "size_t", defValue="", syncMode="ON_GHOST_CREATION") - p.addProperty("rotation", "walberla::mesa_pd::Rot3", defValue="", syncMode="ALWAYS") - p.addProperty("angularVelocity", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") - p.addProperty("torque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") + def __init__(self, particle_storage): + particle_storage.add_property("shapeID", "size_t", defValue="", syncMode="ON_GHOST_CREATION") + particle_storage.add_property("rotation", "walberla::mesa_pd::Rot3", defValue="", syncMode="ALWAYS") + particle_storage.add_property("angularVelocity", "walberla::mesa_pd::Vec3", defValue="real_t(0)", + syncMode="ALWAYS") + particle_storage.add_property("torque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="NEVER") - self.shapes = shapes + self.ps = particle_storage - def generate(self, path): - context = dict() - context["shapes"] = self.shapes + def generate(self, module): + ctx = {'module': module, 'particle': self.ps.get_context()} - generateFile(path, 'data/ShapeStorage.templ.h', context) + generate_file(module['module_path'], 'data/ShapeStorage.templ.h', ctx) diff --git a/python/mesa_pd/data/SparseLinkedCells.py b/python/mesa_pd/data/SparseLinkedCells.py index 516acfd82..b0ee85de8 100644 --- a/python/mesa_pd/data/SparseLinkedCells.py +++ b/python/mesa_pd/data/SparseLinkedCells.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- import numpy as np -from ..utility import generateFile +from ..utility import generate_file + class SparseLinkedCells: - def generate(self, path): - generateFile(path, 'data/SparseLinkedCells.templ.h') + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'data/SparseLinkedCells.templ.h', ctx) diff --git a/python/mesa_pd/data/__init__.py b/python/mesa_pd/data/__init__.py index d09dc6e57..b75df12ce 100644 --- a/python/mesa_pd/data/__init__.py +++ b/python/mesa_pd/data/__init__.py @@ -9,7 +9,6 @@ from .SparseLinkedCells import SparseLinkedCells __all__ = ['ContactHistory', 'ContactStorage', - 'GeometryStorage', 'LinkedCells', 'ParticleStorage', 'SparseLinkedCells'] diff --git a/python/mesa_pd/kernel/DetectAndStoreContacts.py b/python/mesa_pd/kernel/DetectAndStoreContacts.py index 8f6c3d9d8..4bcf79712 100644 --- a/python/mesa_pd/kernel/DetectAndStoreContacts.py +++ b/python/mesa_pd/kernel/DetectAndStoreContacts.py @@ -1,25 +1,18 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile - -class DetectAndStoreContacts: - - def __init__(self): - self.accessor = Accessor() - self.accessor.require("uid", "walberla::id_t", access="g") - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("rotation", "walberla::mesa_pd::Rot3", access="g") - self.accessor.require("shape", "BaseShape*", access="g") +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file +class DetectAndStoreContacts: - def getRequirements(self): - return self.accessor - + def __init__(self): + self.context = {'interface': [create_access("uid", "walberla::id_t", access="g"), + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g"), + create_access("position", "walberla::mesa_pd::Vec3", access="g"), + create_access("rotation", "walberla::mesa_pd::Rot3", access="g"), + create_access("shape", "BaseShape*", access="g")]} - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/DetectAndStoreContacts.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/DetectAndStoreContacts.templ.h', ctx) diff --git a/python/mesa_pd/kernel/DoubleCast.py b/python/mesa_pd/kernel/DoubleCast.py index 4d132f79a..04722840b 100644 --- a/python/mesa_pd/kernel/DoubleCast.py +++ b/python/mesa_pd/kernel/DoubleCast.py @@ -1,19 +1,14 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class DoubleCast: - def __init__(self, shapes): - self.shapes = shapes - self.accessor = Accessor() - self.accessor.require("shape", "BaseShape*", access="g") - def getRequirements(self): - return self.accessor +class DoubleCast: + def __init__(self, particle_storage): + self.ps = particle_storage + self.context = {'interface': [create_access("shape", "BaseShape*", access="g")]} - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - context["shapes"] = self.shapes - generateFile(path, 'kernel/DoubleCast.templ.h', context) + def generate(self, module): + context = {'module': module, 'particle': self.ps.get_context(), **self.context} + generate_file(module['module_path'], 'kernel/DoubleCast.templ.h', context) diff --git a/python/mesa_pd/kernel/ExplicitEuler.py b/python/mesa_pd/kernel/ExplicitEuler.py index a610c7c27..b8cbb0eb2 100644 --- a/python/mesa_pd/kernel/ExplicitEuler.py +++ b/python/mesa_pd/kernel/ExplicitEuler.py @@ -1,26 +1,24 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class ExplicitEuler: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("invMass", "walberla::real_t", access="g" ) - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - def getRequirements(self): - return self.accessor +class ExplicitEuler: + def __init__(self): + self.context = dict() + self.context['interface'] = [create_access("position", "walberla::mesa_pd::Vec3", access="gs"), + create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gs"), + create_access("invMass", "walberla::real_t", access="g"), + create_access("force", "walberla::mesa_pd::Vec3", access="gs"), + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")] - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/ExplicitEuler.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/ExplicitEuler.templ.h', ctx) - context["InterfaceTestName"] = "ExplicitEulerInterfaceCheck" - context["KernelInclude"] = "kernel/ExplicitEuler.h" - context["ExplicitInstantiation"] = "template void kernel::ExplicitEuler::operator()(const size_t p_idx1, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "ExplicitEulerInterfaceCheck" + ctx["KernelInclude"] = "kernel/ExplicitEuler.h" + ctx["ExplicitInstantiation"] = "template void kernel::ExplicitEuler::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/ExplicitEulerInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/ExplicitEulerWithShape.py b/python/mesa_pd/kernel/ExplicitEulerWithShape.py index cdedaa242..9179e7b70 100644 --- a/python/mesa_pd/kernel/ExplicitEulerWithShape.py +++ b/python/mesa_pd/kernel/ExplicitEulerWithShape.py @@ -1,30 +1,28 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class ExplicitEulerWithShape: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("invMass", "walberla::real_t", access="g" ) - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("rotation", "walberla::mesa_pd::Rot3", access="gs") - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("invInertiaBF", "walberla::mesa_pd::Mat3", access="g" ) - self.accessor.require("torque", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - def getRequirements(self): - return self.accessor +class ExplicitEulerWithShape: + def __init__(self): + self.context = dict() + self.context['interface'] = [create_access("position", "walberla::mesa_pd::Vec3", access="gs"), + create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gs"), + create_access("invMass", "walberla::real_t", access="g"), + create_access("force", "walberla::mesa_pd::Vec3", access="gs"), + create_access("rotation", "walberla::mesa_pd::Rot3", access="gs"), + create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="gs"), + create_access("invInertiaBF", "walberla::mesa_pd::Mat3", access="g"), + create_access("torque", "walberla::mesa_pd::Vec3", access="gs"), + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")] - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/ExplicitEulerWithShape.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/ExplicitEulerWithShape.templ.h', ctx) - context["InterfaceTestName"] = "ExplicitEulerWithShapeInterfaceCheck" - context["KernelInclude"] = "kernel/ExplicitEulerWithShape.h" - context["ExplicitInstantiation"] = "template void kernel::ExplicitEulerWithShape::operator()(const size_t p_idx1, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "ExplicitEulerWithShapeInterfaceCheck" + ctx["KernelInclude"] = "kernel/ExplicitEulerWithShape.h" + ctx["ExplicitInstantiation"] = "template void kernel::ExplicitEulerWithShape::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/ForceLJ.py b/python/mesa_pd/kernel/ForceLJ.py index 4af22f77b..45c22f298 100644 --- a/python/mesa_pd/kernel/ForceLJ.py +++ b/python/mesa_pd/kernel/ForceLJ.py @@ -1,26 +1,24 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class ForceLJ: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("type", "uint_t", access="g") - def getRequirements(self): - return self.accessor +class ForceLJ: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("type", "uint_t", access="g")) - def generate(self, path): - context = dict() - context["parameters"] = ["epsilon", "sigma"] - context["interface"] = self.accessor.properties + def generate(self, module): + ctx = {'module': module, **self.context} + ctx["parameters"] = ["epsilon", "sigma"] - generateFile(path, 'kernel/ForceLJ.templ.h', context) + generate_file(module['module_path'], 'kernel/ForceLJ.templ.h', ctx) - context["InterfaceTestName"] = "ForceLJInterfaceCheck" - context["KernelInclude"] = "kernel/ForceLJ.h" - context["ExplicitInstantiation"] = "template void kernel::ForceLJ::operator()(const size_t p_idx1, const size_t p_idx2, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "ForceLJInterfaceCheck" + ctx["KernelInclude"] = "kernel/ForceLJ.h" + ctx["ExplicitInstantiation"] = "template void kernel::ForceLJ::operator()(const size_t p_idx1, const size_t p_idx2, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/ForceLJInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/HCSITSRelaxationStep.py b/python/mesa_pd/kernel/HCSITSRelaxationStep.py index bb80d20ac..f29ae75cb 100644 --- a/python/mesa_pd/kernel/HCSITSRelaxationStep.py +++ b/python/mesa_pd/kernel/HCSITSRelaxationStep.py @@ -1,32 +1,43 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from ..Container import Container -from mesa_pd.utility import generateFile - -class HCSITSRelaxationStep(Container): - def __init__(self): - super().__init__() - self.addProperty("maxSubIterations", "size_t", defValue = "20") - self.addProperty("relaxationModel", "RelaxationModel", defValue = "InelasticFrictionlessContact") - self.addProperty("deltaMax", "real_t", defValue = "0") - self.addProperty("cor", "real_t", defValue = "real_t(0.2)") - - self.accessor = Accessor() - self.accessor.require("uid", "walberla::id_t", access="g") - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("invMass", "walberla::real_t", access="g" ) - self.accessor.require("invInertia", "walberla::mesa_pd::Mat3", access="g" ) - self.accessor.require("dv", "walberla::mesa_pd::Vec3", access="gr" ) - self.accessor.require("dw", "walberla::mesa_pd::Vec3", access="gr" ) - - def getRequirements(self): - return self.accessor - - def generate(self, path): - context = dict() - context["properties"] = self.properties - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/HCSITSRelaxationStep.templ.h', context) +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + + +def create_property(name, type, defValue=""): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + """ + + return {'name': name, 'type': type, 'defValue': defValue} + + +class HCSITSRelaxationStep(): + def __init__(self): + self.context = {'properties': [], 'interface': []} + + self.context['properties'].append(create_property("maxSubIterations", "size_t", defValue="20")) + self.context['properties'].append( + create_property("relaxationModel", "RelaxationModel", defValue="InelasticFrictionlessContact")) + self.context['properties'].append(create_property("deltaMax", "real_t", defValue="0")) + self.context['properties'].append(create_property("cor", "real_t", defValue="real_t(0.2)")) + + self.context['interface'].append(create_access("uid", "walberla::id_t", access="g")) + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("invMass", "walberla::real_t", access="g")) + self.context['interface'].append(create_access("invInertia", "walberla::mesa_pd::Mat3", access="g")) + self.context['interface'].append(create_access("dv", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("dw", "walberla::mesa_pd::Vec3", access="gr")) + + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/HCSITSRelaxationStep.templ.h', ctx) diff --git a/python/mesa_pd/kernel/HeatConduction.py b/python/mesa_pd/kernel/HeatConduction.py index 2a6f31337..1135cf199 100644 --- a/python/mesa_pd/kernel/HeatConduction.py +++ b/python/mesa_pd/kernel/HeatConduction.py @@ -1,26 +1,25 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile, checkInterface +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class HeatConduction: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("temperature", "walberla::real_t", access="g") - self.accessor.require("heatFlux", "walberla::real_t", access="gsr") - self.accessor.require("type", "uint_t", access="g") - def getRequirements(self): - return self.accessor +class HeatConduction: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("temperature", "walberla::real_t", access="g")) + self.context['interface'].append(create_access("heatFlux", "walberla::real_t", access="gsr")) + self.context['interface'].append(create_access("type", "uint_t", access="g")) - def generate(self, path): - context = dict() - context["parameters"] = ["conductance"] - context["interface"] = self.accessor.properties + def generate(self, module): + ctx = {'module': module, + **self.context, + "parameters": ["conductance"]} - generateFile(path, 'kernel/HeatConduction.templ.h', context) + generate_file(module['module_path'], 'kernel/HeatConduction.templ.h', ctx) - context["InterfaceTestName"] = "HeatConductionInterfaceCheck" - context["KernelInclude"] = "kernel/HeatConduction.h" - context["ExplicitInstantiation"] = "template void kernel::HeatConduction::operator()(const size_t p_idx1, const size_t p_idx2, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "HeatConductionInterfaceCheck" + ctx["KernelInclude"] = "kernel/HeatConduction.h" + ctx["ExplicitInstantiation"] = "template void kernel::HeatConduction::operator()(const size_t p_idx1, const size_t p_idx2, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/HeatConductionInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/InitContactsForHCSITS.py b/python/mesa_pd/kernel/InitContactsForHCSITS.py index 54da9536a..545975d4b 100644 --- a/python/mesa_pd/kernel/InitContactsForHCSITS.py +++ b/python/mesa_pd/kernel/InitContactsForHCSITS.py @@ -1,28 +1,40 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from ..Container import Container -from mesa_pd.utility import generateFile - -class InitContactsForHCSITS(Container): - def __init__(self): - super().__init__() - self.addProperty("erp", "real_t", defValue = "real_t(0.8)") - self.addProperty("maximumPenetration", "real_t", defValue ="0") - - self.paccessor = Accessor() - self.paccessor.require("uid", "walberla::id_t", access="g") - self.paccessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.paccessor.require("invInertia", "walberla::mesa_pd::Mat3", access="g" ) - self.paccessor.require("invMass", "walberla::real_t", access="g" ) - - - def getRequirements(self): - return self.paccessor - - def generate(self, path): - context = dict() - context["properties"] = self.properties - context["material_parameters"] = ["friction"] - context["interface"] = self.paccessor.properties - generateFile(path, 'kernel/InitContactsForHCSITS.templ.h', context) +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + + +def create_property(name, type, defValue=""): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + """ + + return {'name': name, 'type': type, 'defValue': defValue} + + +class InitContactsForHCSITS: + def __init__(self): + self.context = {'properties': [], 'interface': []} + + self.context['properties'].append(create_property("erp", "real_t", defValue="real_t(0.8)")) + self.context['properties'].append(create_property("maximumPenetration", "real_t", defValue="0")) + + self.context['interface'].append(create_access("uid", "walberla::id_t", access="g")) + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("invInertia", "walberla::mesa_pd::Mat3", access="g")) + self.context['interface'].append(create_access("invMass", "walberla::real_t", access="g")) + + def getRequirements(self): + return self.paccessor + + def generate(self, module): + ctx = {'module': module, **self.context} + ctx["material_parameters"] = ["friction"] + generate_file(module['module_path'], 'kernel/InitContactsForHCSITS.templ.h', ctx) diff --git a/python/mesa_pd/kernel/InitParticlesForHCSITS.py b/python/mesa_pd/kernel/InitParticlesForHCSITS.py index ca0148cab..09cd05c84 100644 --- a/python/mesa_pd/kernel/InitParticlesForHCSITS.py +++ b/python/mesa_pd/kernel/InitParticlesForHCSITS.py @@ -1,31 +1,42 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from ..Container import Container -from mesa_pd.utility import generateFile - -class InitParticlesForHCSITS(Container): - def __init__(self): - super().__init__() - self.addProperty("globalAcceleration", "walberla::mesa_pd::Vec3", defValue = "0") - - self.accessor = Accessor() - self.accessor.require("uid", "walberla::id_t", access="g") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="gr") - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="gr") - self.accessor.require("invMass", "walberla::real_t", access="g" ) - self.accessor.require("inertia", "walberla::mesa_pd::Mat3", access="g" ) - self.accessor.require("invInertia", "walberla::mesa_pd::Mat3", access="g" ) - self.accessor.require("dv", "walberla::mesa_pd::Vec3", access="gr" ) - self.accessor.require("dw", "walberla::mesa_pd::Vec3", access="gr" ) - self.accessor.require("torque", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="r" ) - - def getRequirements(self): - return self.accessor - - def generate(self, path): - context = dict() - context["properties"] = self.properties - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/InitParticlesForHCSITS.templ.h', context) +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + + +def create_property(name, type, defValue=""): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + """ + + return {'name': name, 'type': type, 'defValue': defValue} + + +class InitParticlesForHCSITS: + def __init__(self): + self.context = {'properties': [], 'interface': []} + + self.context['properties'].append( + create_property("globalAcceleration", "walberla::mesa_pd::Vec3", defValue="0")) + + self.context['interface'].append(create_access("uid", "walberla::id_t", access="g")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("invMass", "walberla::real_t", access="g")) + self.context['interface'].append(create_access("inertia", "walberla::mesa_pd::Mat3", access="g")) + self.context['interface'].append(create_access("invInertia", "walberla::mesa_pd::Mat3", access="g")) + self.context['interface'].append(create_access("dv", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("dw", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="r")) + + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/InitParticlesForHCSITS.templ.h', ctx) diff --git a/python/mesa_pd/kernel/InsertParticleIntoLinkedCells.py b/python/mesa_pd/kernel/InsertParticleIntoLinkedCells.py index 794fab1df..d0ce662ee 100644 --- a/python/mesa_pd/kernel/InsertParticleIntoLinkedCells.py +++ b/python/mesa_pd/kernel/InsertParticleIntoLinkedCells.py @@ -1,19 +1,17 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class InsertParticleIntoLinkedCells: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - self.accessor.require("nextParticle", "size_t", access="gs" ) - def getRequirements(self): - return self.accessor +class InsertParticleIntoLinkedCells: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append( + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")) + self.context['interface'].append(create_access("nextParticle", "size_t", access="gs")) - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/InsertParticleIntoLinkedCells.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/InsertParticleIntoLinkedCells.templ.h', ctx) diff --git a/python/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.py b/python/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.py index 9bb841b01..a1c4d4bbe 100644 --- a/python/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.py +++ b/python/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.py @@ -1,19 +1,17 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class InsertParticleIntoSparseLinkedCells: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - self.accessor.require("nextParticle", "size_t", access="gs" ) - def getRequirements(self): - return self.accessor +class InsertParticleIntoSparseLinkedCells: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append( + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")) + self.context['interface'].append(create_access("nextParticle", "size_t", access="gs")) - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/InsertParticleIntoSparseLinkedCells.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/InsertParticleIntoSparseLinkedCells.templ.h', ctx) diff --git a/python/mesa_pd/kernel/IntegrateParticlesHCSITS.py b/python/mesa_pd/kernel/IntegrateParticlesHCSITS.py index b869d5dec..ac0f06bf5 100644 --- a/python/mesa_pd/kernel/IntegrateParticlesHCSITS.py +++ b/python/mesa_pd/kernel/IntegrateParticlesHCSITS.py @@ -1,30 +1,41 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from ..Container import Container -from mesa_pd.utility import generateFile - -class IntegrateParticlesHCSITS(Container): - def __init__(self): - super().__init__() - self.addProperty("speedLimiterActive", "bool", defValue = "false") - self.addProperty("speedLimitFactor", "real_t", defValue ="real_t(1.0)") - - self.accessor = Accessor() - self.accessor.require("uid", "walberla::id_t", access="g") - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="gr") - self.accessor.require("rotation", "walberla::mesa_pd::Rot3", access="gr") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="gr") - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="gr") - self.accessor.require("dv", "walberla::mesa_pd::Vec3", access="g" ) - self.accessor.require("dw", "walberla::mesa_pd::Vec3", access="g" ) - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - - def getRequirements(self): - return self.accessor - - def generate(self, path): - context = dict() - context["properties"] = self.properties - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/IntegrateParticlesHCSITS.templ.h', context) +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + + +def create_property(name, type, defValue=""): + """ + Parameters + ---------- + name : str + name of the property + type : str + type of the property + defValue : str + default value the property should be initialized with + """ + + return {'name': name, 'type': type, 'defValue': defValue} + + +class IntegrateParticlesHCSITS(): + def __init__(self): + self.context = {'properties': [], 'interface': []} + + self.context['properties'].append(create_property("speedLimiterActive", "bool", defValue="false")) + self.context['properties'].append(create_property("speedLimitFactor", "real_t", defValue="real_t(1.0)")) + + self.context['interface'].append(create_access("uid", "walberla::id_t", access="g")) + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("rotation", "walberla::mesa_pd::Rot3", access="gr")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="gr")) + self.context['interface'].append(create_access("dv", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("dw", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append( + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")) + + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/IntegrateParticlesHCSITS.templ.h', ctx) diff --git a/python/mesa_pd/kernel/LinearSpringDashpot.py b/python/mesa_pd/kernel/LinearSpringDashpot.py index 430a58dc6..747a83f6a 100644 --- a/python/mesa_pd/kernel/LinearSpringDashpot.py +++ b/python/mesa_pd/kernel/LinearSpringDashpot.py @@ -1,26 +1,25 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class LinearSpringDashpot: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("uid", "walberla::id_t", access="g") - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("torque", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("type", "uint_t", access="g") - self.accessor.require("contactHistory", "std::map<walberla::id_t, walberla::mesa_pd::Vec3>", access="gs") - def getRequirements(self): - return self.accessor +class LinearSpringDashpot: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("uid", "walberla::id_t", access="g")) + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("type", "uint_t", access="g")) + self.context['interface'].append( + create_access("contactHistory", "std::map<walberla::id_t, walberla::mesa_pd::Vec3>", access="gs")) - def generate(self, path): - context = dict() - context["parameters"] = ["stiffnessN", "stiffnessT", "dampingN", "dampingT", "frictionCoefficientStatic", "frictionCoefficientDynamic"] - context["interface"] = self.accessor.properties + def generate(self, module): + ctx = {'module': module, **self.context} + ctx["parameters"] = ["stiffnessN", "stiffnessT", "dampingN", "dampingT", "frictionCoefficientStatic", + "frictionCoefficientDynamic"] - generateFile(path, 'kernel/LinearSpringDashpot.templ.h', context) + generate_file(module['module_path'], 'kernel/LinearSpringDashpot.templ.h', ctx) diff --git a/python/mesa_pd/kernel/NonLinearSpringDashpot.py b/python/mesa_pd/kernel/NonLinearSpringDashpot.py index 490d05ff5..33f46d44e 100644 --- a/python/mesa_pd/kernel/NonLinearSpringDashpot.py +++ b/python/mesa_pd/kernel/NonLinearSpringDashpot.py @@ -1,26 +1,25 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class NonLinearSpringDashpot: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("uid", "walberla::id_t", access="g") - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("torque", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("type", "uint_t", access="g") - self.accessor.require("contactHistory", "std::map<walberla::id_t, walberla::mesa_pd::Vec3>", access="gs") - def getRequirements(self): - return self.accessor +class NonLinearSpringDashpot: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("uid", "walberla::id_t", access="g")) + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("type", "uint_t", access="g")) + self.context['interface'].append( + create_access("contactHistory", "std::map<walberla::id_t, walberla::mesa_pd::Vec3>", access="gs")) - def generate(self, path): - context = dict() - context["parameters"] = ["lnCORsqr", "meff", "stiffnessT", "dampingT", "frictionCoefficientStatic", "frictionCoefficientDynamic"] - context["interface"] = self.accessor.properties + def generate(self, module): + ctx = {'module': module, **self.context} + ctx["parameters"] = ["lnCORsqr", "meff", "stiffnessT", "dampingT", "frictionCoefficientStatic", + "frictionCoefficientDynamic"] - generateFile(path, 'kernel/NonLinearSpringDashpot.templ.h', context) + generate_file(module['module_path'], 'kernel/NonLinearSpringDashpot.templ.h', ctx) diff --git a/python/mesa_pd/kernel/SingleCast.py b/python/mesa_pd/kernel/SingleCast.py index ff253dfd0..1af856e59 100644 --- a/python/mesa_pd/kernel/SingleCast.py +++ b/python/mesa_pd/kernel/SingleCast.py @@ -1,19 +1,15 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class SingleCast: - def __init__(self, shapes): - self.shapes = shapes - self.accessor = Accessor() - self.accessor.require("shape", "BaseShape*", access="g") - - def getRequirements(self): - return self.accessor - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - context["shapes"] = self.shapes - generateFile(path, 'kernel/SingleCast.templ.h', context) +class SingleCast: + def __init__(self, particle_storage): + self.ps = particle_storage + self.context = {'interface': []} + self.context['interface'].append(create_access("shape", "BaseShape*", access="g")) + + def generate(self, module): + ctx = {'module': module, 'particle': self.ps.get_context(), **self.context} + generate_file(module['module_path'], 'kernel/SingleCast.templ.h', ctx) diff --git a/python/mesa_pd/kernel/SpringDashpot.py b/python/mesa_pd/kernel/SpringDashpot.py index e7d90a843..8b7a783b4 100644 --- a/python/mesa_pd/kernel/SpringDashpot.py +++ b/python/mesa_pd/kernel/SpringDashpot.py @@ -1,30 +1,30 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile, checkInterface +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class SpringDashpot: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="g") - self.accessor.require("torque", "walberla::mesa_pd::Vec3", access="r" ) - self.accessor.require("type", "uint_t", access="g") - self.accessor.require("contactHistory", "std::map<walberla::id_t, walberla::mesa_pd::Vec3>", access="gs") - def getRequirements(self): - return self.accessor +class SpringDashpot: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="g")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="r")) + self.context['interface'].append(create_access("type", "uint_t", access="g")) + self.context['interface'].append( + create_access("contactHistory", "std::map<walberla::id_t, walberla::mesa_pd::Vec3>", access="gs")) - def generate(self, path): - context = dict() - context["parameters"] = ["stiffness", "dampingN", "dampingT", "friction"] - context["interface"] = self.accessor.properties + def generate(self, module): + ctx = {'module': module, **self.context} + ctx["parameters"] = ["stiffness", "dampingN", "dampingT", "friction"] - generateFile(path, 'kernel/SpringDashpot.templ.h', context) + generate_file(module['module_path'], 'kernel/SpringDashpot.templ.h', ctx) - context["InterfaceTestName"] = "SpringDashpotInterfaceCheck" - context["KernelInclude"] = "kernel/SpringDashpot.h" - context["ExplicitInstantiation"] = "template void kernel::SpringDashpot::operator()(const size_t p_idx1, const size_t p_idx2, Accessor& ac, const Vec3& contactPoint, const Vec3& contactNormal, const real_t& penetrationDepth) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "SpringDashpotInterfaceCheck" + ctx["KernelInclude"] = "kernel/SpringDashpot.h" + ctx[ + "ExplicitInstantiation"] = "template void kernel::SpringDashpot::operator()(const size_t p_idx1, const size_t p_idx2, Accessor& ac, const Vec3& contactPoint, const Vec3& contactNormal, const real_t& penetrationDepth) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/SpringDashpotInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/TemperatureIntegration.py b/python/mesa_pd/kernel/TemperatureIntegration.py index 68cca40f2..426a9b387 100644 --- a/python/mesa_pd/kernel/TemperatureIntegration.py +++ b/python/mesa_pd/kernel/TemperatureIntegration.py @@ -1,25 +1,24 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class TemperatureIntegration: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("temperature", "walberla::real_t", access="gs") - self.accessor.require("heatFlux", "walberla::real_t", access="gs") - self.accessor.require("type", "uint_t", access="g") - def getRequirements(self): - return self.accessor +class TemperatureIntegration: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("temperature", "walberla::real_t", access="gs")) + self.context['interface'].append(create_access("heatFlux", "walberla::real_t", access="gs")) + self.context['interface'].append(create_access("type", "uint_t", access="g")) - def generate(self, path): - context = dict() - context["parameters"] = ["invHeatCapacity"] - context["interface"] = self.accessor.properties - generateFile(path, 'kernel/TemperatureIntegration.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + ctx["parameters"] = ["invHeatCapacity"] + generate_file(module['module_path'], 'kernel/TemperatureIntegration.templ.h', ctx) - context["InterfaceTestName"] = "TemperatureIntegrationInterfaceCheck" - context["KernelInclude"] = "kernel/TemperatureIntegration.h" - context["ExplicitInstantiation"] = "template void kernel::TemperatureIntegration::operator()(const size_t p_idx1, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "TemperatureIntegrationInterfaceCheck" + ctx["KernelInclude"] = "kernel/TemperatureIntegration.h" + ctx[ + "ExplicitInstantiation"] = "template void kernel::TemperatureIntegration::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/VelocityVerlet.py b/python/mesa_pd/kernel/VelocityVerlet.py index 391b77070..8d2d42a35 100644 --- a/python/mesa_pd/kernel/VelocityVerlet.py +++ b/python/mesa_pd/kernel/VelocityVerlet.py @@ -1,29 +1,29 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file -class VelocityVerlet: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("invMass", "walberla::real_t", access="g" ) - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("oldForce", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - def getRequirements(self): - return self.accessor +class VelocityVerlet: + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("invMass", "walberla::real_t", access="g")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("oldForce", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append( + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")) - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties + def generate(self, module): + ctx = {'module': module, **self.context} - generateFile(path, 'kernel/VelocityVerlet.templ.h', context) + generate_file(module['module_path'], 'kernel/VelocityVerlet.templ.h', ctx) - context["InterfaceTestName"] = "VelocityVerletInterfaceCheck" - context["KernelInclude"] = "kernel/VelocityVerlet.h" - context["ExplicitInstantiation"] = "template void kernel::VelocityVerletPreForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;\n" +\ - "template void kernel::VelocityVerletPostForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp') + ctx["InterfaceTestName"] = "VelocityVerletInterfaceCheck" + ctx["KernelInclude"] = "kernel/VelocityVerlet.h" + ctx[ + "ExplicitInstantiation"] = "template void kernel::VelocityVerletPreForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;\n" + \ + "template void kernel::VelocityVerletPostForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/VelocityVerletInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/VelocityVerletWithShape.py b/python/mesa_pd/kernel/VelocityVerletWithShape.py index 8dbd50a0b..e3d21c595 100644 --- a/python/mesa_pd/kernel/VelocityVerletWithShape.py +++ b/python/mesa_pd/kernel/VelocityVerletWithShape.py @@ -1,36 +1,39 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + class VelocityVerletWithShape: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("position", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("linearVelocity", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("invMass", "walberla::real_t", access="g" ) - self.accessor.require("force", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("oldForce", "walberla::mesa_pd::Vec3", access="gs" ) - - self.accessor.require("rotation", "walberla::mesa_pd::Rot3", access="gs") - self.accessor.require("angularVelocity", "walberla::mesa_pd::Vec3", access="gs") - self.accessor.require("invInertiaBF", "walberla::mesa_pd::Mat3", access="g" ) - self.accessor.require("torque", "walberla::mesa_pd::Vec3", access="gs" ) - self.accessor.require("oldTorque", "walberla::mesa_pd::Vec3", access="gs" ) - - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - - def getRequirements(self): - return self.accessor - - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - - generateFile(path, 'kernel/VelocityVerletWithShape.templ.h', context) - - context["InterfaceTestName"] = "VelocityVerletWithShapeInterfaceCheck" - context["KernelInclude"] = "kernel/VelocityVerletWithShape.h" - context["ExplicitInstantiation"] = "template void kernel::VelocityVerletWithShapePreForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;\n" +\ - "template void kernel::VelocityVerletWithShapePostForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;" - generateFile(path, 'tests/CheckInterface.templ.cpp', context, '../../tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp') + def __init__(self): + self.context = {'interface': []} + self.context['interface'].append(create_access("position", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("invMass", "walberla::real_t", access="g")) + self.context['interface'].append(create_access("force", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("oldForce", "walberla::mesa_pd::Vec3", access="gs")) + + self.context['interface'].append(create_access("rotation", "walberla::mesa_pd::Rot3", access="gs")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("invInertiaBF", "walberla::mesa_pd::Mat3", access="g")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("oldTorque", "walberla::mesa_pd::Vec3", access="gs")) + + self.context['interface'].append( + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")) + + def getRequirements(self): + return self.accessor + + def generate(self, module): + ctx = {'module': module, **self.context} + + generate_file(module['module_path'], 'kernel/VelocityVerletWithShape.templ.h', ctx) + + ctx["InterfaceTestName"] = "VelocityVerletWithShapeInterfaceCheck" + ctx["KernelInclude"] = "kernel/VelocityVerletWithShape.h" + ctx[ + "ExplicitInstantiation"] = "template void kernel::VelocityVerletWithShapePreForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;\n" + \ + "template void kernel::VelocityVerletWithShapePostForceUpdate::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp') diff --git a/python/mesa_pd/mpi/BroadcastProperty.py b/python/mesa_pd/mpi/BroadcastProperty.py index 4e6109ae4..99a2c1fd8 100644 --- a/python/mesa_pd/mpi/BroadcastProperty.py +++ b/python/mesa_pd/mpi/BroadcastProperty.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- -from ..utility import generateFile +from ..utility import generate_file + class BroadcastProperty: - def generate(self, path): - generateFile(path, 'mpi/BroadcastProperty.templ.h') + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'mpi/BroadcastProperty.templ.h', ctx) diff --git a/python/mesa_pd/mpi/ClearNextNeighborSync.py b/python/mesa_pd/mpi/ClearNextNeighborSync.py index e78fecc88..0cb341c4a 100644 --- a/python/mesa_pd/mpi/ClearNextNeighborSync.py +++ b/python/mesa_pd/mpi/ClearNextNeighborSync.py @@ -1,18 +1,17 @@ # -*- coding: utf-8 -*- -from mesa_pd.accessor import Accessor -from mesa_pd.utility import generateFile +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + class ClearNextNeighborSync: - def __init__(self): - self.accessor = Accessor() - self.accessor.require("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") - self.accessor.require("ghostOwners", "std::vector<int>", access="r") + def __init__(self): + self.context = {'properties': [], 'interface': []} - def getRequirements(self): - return self.accessor + self.context['interface'].append( + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g")) + self.context['interface'].append(create_access("ghostOwners", "std::vector<int>", access="r")) - def generate(self, path): - context = dict() - context["interface"] = self.accessor.properties - generateFile(path, 'mpi/ClearNextNeighborSync.templ.h', context) + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'mpi/ClearNextNeighborSync.templ.h', ctx) diff --git a/python/mesa_pd/mpi/Notifications.py b/python/mesa_pd/mpi/Notifications.py new file mode 100644 index 000000000..4a87ee426 --- /dev/null +++ b/python/mesa_pd/mpi/Notifications.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +from ..utility import generate_file + +class Notifications: + def __init__(self, particle_storage): + self.ps = particle_storage + + def generate(self, module): + ctx = {'module': module, 'particle' : self.ps.get_context()} + + generate_file(module['module_path'], 'mpi/notifications/ForceTorqueNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/HeatFluxNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParseMessage.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleCopyNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleGhostCopyNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/NewGhostParticleNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleMigrationNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleRemoteMigrationNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleRemovalInformationNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleRemovalNotification.templ.h', ctx) + generate_file(module['module_path'], 'mpi/notifications/ParticleUpdateNotification.templ.h', ctx) diff --git a/python/mesa_pd/mpi/ReduceContactHistory.py b/python/mesa_pd/mpi/ReduceContactHistory.py index f2a4c797a..cf4e18582 100644 --- a/python/mesa_pd/mpi/ReduceContactHistory.py +++ b/python/mesa_pd/mpi/ReduceContactHistory.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- -from ..utility import generateFile +from ..utility import generate_file + class ReduceContactHistory: - def generate(self, path): - generateFile(path, 'mpi/ReduceContactHistory.templ.h') + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'mpi/ReduceContactHistory.templ.h', ctx) diff --git a/python/mesa_pd/mpi/ReduceProperty.py b/python/mesa_pd/mpi/ReduceProperty.py index b630a0dd0..744661043 100644 --- a/python/mesa_pd/mpi/ReduceProperty.py +++ b/python/mesa_pd/mpi/ReduceProperty.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- -from ..utility import generateFile +from ..utility import generate_file + class ReduceProperty: - def generate(self, path): - generateFile(path, 'mpi/ReduceProperty.templ.h') + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'mpi/ReduceProperty.templ.h', ctx) diff --git a/python/mesa_pd/mpi/ShapePackUnpack.py b/python/mesa_pd/mpi/ShapePackUnpack.py index cb52010d7..2bb60d77e 100644 --- a/python/mesa_pd/mpi/ShapePackUnpack.py +++ b/python/mesa_pd/mpi/ShapePackUnpack.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- -from ..utility import generateFile +from ..utility import generate_file + class ShapePackUnpack: - def __init__(self, shapes): - self.shapes = shapes - def generate(self, path): - context = dict() - context["shapes"] = self.shapes - generateFile(path, 'mpi/ShapePackUnpack.templ.h', context) + def __init__(self, particle_storage): + self.ps = particle_storage + + def generate(self, module): + ctx = {'module': module, 'particle': self.ps.get_context()} + generate_file(module['module_path'], 'mpi/ShapePackUnpack.templ.h', ctx) diff --git a/python/mesa_pd/mpi/SyncGhostOwners.py b/python/mesa_pd/mpi/SyncGhostOwners.py index 320a8f4c7..e4c8b203f 100644 --- a/python/mesa_pd/mpi/SyncGhostOwners.py +++ b/python/mesa_pd/mpi/SyncGhostOwners.py @@ -1,16 +1,22 @@ # -*- coding: utf-8 -*- -from ..utility import generateFile +from ..utility import generate_file + class SyncGhostOwners: - def __init__(self, p): - p.addProperty("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") - p.addProperty("interactionRadius", "walberla::real_t", defValue="real_t(0)", syncMode="ON_GHOST_CREATION") - p.addProperty("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", syncMode="ON_GHOST_CREATION") - p.addProperty("owner", "int", defValue="-1", syncMode="ON_GHOST_CREATION") - p.addProperty("ghostOwners", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", syncMode="NEVER") - p.addProperty("neighborState", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", syncMode="NEVER") + def __init__(self, particle_storage): + particle_storage.add_property("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + particle_storage.add_property("interactionRadius", "walberla::real_t", defValue="real_t(0)", + syncMode="ON_GHOST_CREATION") + particle_storage.add_property("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", + syncMode="ON_GHOST_CREATION") + particle_storage.add_property("owner", "int", defValue="-1", syncMode="ON_GHOST_CREATION") + particle_storage.add_property("ghostOwners", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", + syncMode="NEVER") + particle_storage.add_property("neighborState", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", + syncMode="NEVER") - def generate(self, path): - generateFile(path, 'mpi/SyncGhostOwners.templ.h') - generateFile(path, 'mpi/SyncGhostOwners.templ.cpp') + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'mpi/SyncGhostOwners.templ.h', ctx) + generate_file(module['module_path'], 'mpi/SyncGhostOwners.templ.cpp', ctx) diff --git a/python/mesa_pd/mpi/SyncNextNeighbors.py b/python/mesa_pd/mpi/SyncNextNeighbors.py index 703b9a226..71a9e8cfa 100644 --- a/python/mesa_pd/mpi/SyncNextNeighbors.py +++ b/python/mesa_pd/mpi/SyncNextNeighbors.py @@ -1,15 +1,20 @@ # -*- coding: utf-8 -*- -from ..utility import generateFile +from ..utility import generate_file + class SyncNextNeighbors: - def __init__(self, p): - p.addProperty("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") - p.addProperty("interactionRadius", "walberla::real_t", defValue="real_t(0)", syncMode="ON_GHOST_CREATION") - p.addProperty("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", syncMode="ON_GHOST_CREATION") - p.addProperty("owner", "int", defValue="-1", syncMode="ON_GHOST_CREATION") - p.addProperty("ghostOwners", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", syncMode="NEVER") - - def generate(self, path): - generateFile(path, 'mpi/SyncNextNeighbors.templ.h') - generateFile(path, 'mpi/SyncNextNeighbors.templ.cpp') + def __init__(self, particle_storage): + particle_storage.add_property("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + particle_storage.add_property("interactionRadius", "walberla::real_t", defValue="real_t(0)", + syncMode="ON_GHOST_CREATION") + particle_storage.add_property("flags", "walberla::mesa_pd::data::particle_flags::FlagT", defValue="", + syncMode="ON_GHOST_CREATION") + particle_storage.add_property("owner", "int", defValue="-1", syncMode="ON_GHOST_CREATION") + particle_storage.add_property("ghostOwners", "std::unordered_set<walberla::mpi::MPIRank>", defValue="", + syncMode="NEVER") + + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'mpi/SyncNextNeighbors.templ.h', ctx) + generate_file(module['module_path'], 'mpi/SyncNextNeighbors.templ.cpp', ctx) diff --git a/python/mesa_pd/mpi/SyncNextNeighborsNoGhosts.py b/python/mesa_pd/mpi/SyncNextNeighborsNoGhosts.py new file mode 100644 index 000000000..d29a5471e --- /dev/null +++ b/python/mesa_pd/mpi/SyncNextNeighborsNoGhosts.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +from ..utility import generate_file + + +class SyncNextNeighborsNoGhosts: + def __init__(self, particle_storage): + particle_storage.add_property("position", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ALWAYS") + particle_storage.add_property("owner", "int", defValue="-1", syncMode="ON_GHOST_CREATION") + + def generate(self, module): + ctx = {'module': module} + generate_file(module['module_path'], 'mpi/SyncNextNeighborsNoGhosts.templ.h', ctx) + generate_file(module['module_path'], 'mpi/SyncNextNeighborsNoGhosts.templ.cpp', ctx) diff --git a/python/mesa_pd/mpi/__init__.py b/python/mesa_pd/mpi/__init__.py index c319a8fec..223a70c04 100644 --- a/python/mesa_pd/mpi/__init__.py +++ b/python/mesa_pd/mpi/__init__.py @@ -2,11 +2,13 @@ from .BroadcastProperty import BroadcastProperty from .ClearNextNeighborSync import ClearNextNeighborSync +from .Notifications import Notifications from .ReduceContactHistory import ReduceContactHistory from .ReduceProperty import ReduceProperty from .ShapePackUnpack import ShapePackUnpack from .SyncGhostOwners import SyncGhostOwners from .SyncNextNeighbors import SyncNextNeighbors +from .SyncNextNeighborsNoGhosts import SyncNextNeighborsNoGhosts __all__ = ['BroadcastProperty', 'ClearNextNeighborSync', @@ -15,4 +17,5 @@ __all__ = ['BroadcastProperty', 'ShapePackUnpack', 'SyncGhostOwners', 'SyncNextNeighbors', + 'SyncNextNeighborsNoGhosts' ] diff --git a/python/mesa_pd/templates/data/ShapeStorage.templ.h b/python/mesa_pd/templates/data/ShapeStorage.templ.h index 8cede0992..230f6a923 100644 --- a/python/mesa_pd/templates/data/ShapeStorage.templ.h +++ b/python/mesa_pd/templates/data/ShapeStorage.templ.h @@ -29,7 +29,7 @@ #include <mesa_pd/data/DataTypes.h> #include <mesa_pd/data/ParticleStorage.h> #include <mesa_pd/data/shape/BaseShape.h> -{%- for shape in shapes %} +{%- for shape in particle.shapes %} #include <mesa_pd/data/shape/{{shape}}.h> {%- endfor %} @@ -58,8 +58,8 @@ struct ShapeStorage ReturnType doubleDispatch( ParticleStorage& ps, size_t idx, size_t idy, func& f ); }; //Make sure that no two different shapes have the same unique identifier! -{%- for shape in shapes[1:] %} -static_assert( {{shapes[0]}}::SHAPE_TYPE != {{shape}}::SHAPE_TYPE, "Shape types have to be different!" ); +{%- for shape in particle.shapes[1:] %} +static_assert( {{particle.shapes[0]}}::SHAPE_TYPE != {{shape}}::SHAPE_TYPE, "Shape types have to be different!" ); {%- endfor %} template <typename ShapeT, typename... Args> @@ -76,7 +76,7 @@ ReturnType ShapeStorage::singleDispatch( ParticleStorage& ps, size_t idx, func& switch (shapes[ps.getShapeID(idx)]->getShapeType()) { - {%- for shape in shapes %} + {%- for shape in particle.shapes %} case {{shape}}::SHAPE_TYPE : return f(ps, idx, *static_cast<{{shape}}*>(shapes[ps.getShapeID(idx)].get())); {%- endfor %} default : WALBERLA_ABORT("Shape type (" << shapes[ps.getShapeID(idx)]->getShapeType() << ") could not be determined!"); @@ -91,11 +91,11 @@ ReturnType ShapeStorage::doubleDispatch( ParticleStorage& ps, size_t idx, size_t switch (shapes[ps.getShapeID(idx)]->getShapeType()) { - {%- for shape1 in shapes %} + {%- for shape1 in particle.shapes %} case {{shape1}}::SHAPE_TYPE : switch (shapes[ps.getShapeID(idy)]->getShapeType()) { - {%- for shape2 in shapes %} + {%- for shape2 in particle.shapes %} case {{shape2}}::SHAPE_TYPE : return f(ps, idx, *static_cast<{{shape1}}*>(shapes[ps.getShapeID(idx)].get()), diff --git a/python/mesa_pd/templates/kernel/DoubleCast.templ.h b/python/mesa_pd/templates/kernel/DoubleCast.templ.h index 68cc2b611..adc3caf3c 100644 --- a/python/mesa_pd/templates/kernel/DoubleCast.templ.h +++ b/python/mesa_pd/templates/kernel/DoubleCast.templ.h @@ -29,7 +29,7 @@ #include <mesa_pd/data/DataTypes.h> #include <mesa_pd/data/IAccessor.h> #include <mesa_pd/data/shape/BaseShape.h> -{%- for shape in shapes %} +{%- for shape in particle.shapes %} #include <mesa_pd/data/shape/{{shape}}.h> {%- endfor %} @@ -74,11 +74,11 @@ auto DoubleCast::operator()( size_t idx, size_t idy, Accessor& ac, func& f, Args switch (ac.getShape(idx)->getShapeType()) { - {%- for shape1 in shapes %} + {%- for shape1 in particle.shapes %} case {{shape1}}::SHAPE_TYPE : switch (ac.getShape(idy)->getShapeType()) { - {%- for shape2 in shapes %} + {%- for shape2 in particle.shapes %} case {{shape2}}::SHAPE_TYPE : return f(idx, idy, *static_cast<{{shape1}}*>(ac.getShape(idx)), diff --git a/python/mesa_pd/templates/kernel/SingleCast.templ.h b/python/mesa_pd/templates/kernel/SingleCast.templ.h index d9d771fd9..eda737d63 100644 --- a/python/mesa_pd/templates/kernel/SingleCast.templ.h +++ b/python/mesa_pd/templates/kernel/SingleCast.templ.h @@ -29,7 +29,7 @@ #include <mesa_pd/data/DataTypes.h> #include <mesa_pd/data/IAccessor.h> #include <mesa_pd/data/shape/BaseShape.h> -{%- for shape in shapes %} +{%- for shape in particle.shapes %} #include <mesa_pd/data/shape/{{shape}}.h> {%- endfor %} @@ -73,7 +73,7 @@ auto SingleCast::operator()( size_t idx, Accessor& ac, func& f, Args&&... args ) using namespace mesa_pd::data; switch (ac.getShape(idx)->getShapeType()) { - {%- for shape in shapes %} + {%- for shape in particle.shapes %} case {{shape}}::SHAPE_TYPE : return f(idx, *static_cast<{{shape}}*>(ac.getShape(idx)), std::forward<Args>(args)...); {%- endfor %} default : WALBERLA_ABORT("Shape type (" << ac.getShape(idx)->getShapeType() << ") could not be determined!"); diff --git a/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h b/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h index 47e5bd7fc..2031f6659 100644 --- a/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h +++ b/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h @@ -27,7 +27,7 @@ #pragma once #include <mesa_pd/data/shape/BaseShape.h> -{%- for shape in shapes %} +{%- for shape in particle.shapes %} #include <mesa_pd/data/shape/{{shape}}.h> {%- endfor %} @@ -61,7 +61,7 @@ namespace mpi { buf >> shapeType; switch (shapeType) { - {%- for shape in shapes %} + {%- for shape in particle.shapes %} case {{shape}}::SHAPE_TYPE : bs = std::make_unique<mesa_pd::data::{{shape}}>(); bs->unpack(buf); diff --git a/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp new file mode 100644 index 000000000..bab7acfcc --- /dev/null +++ b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp @@ -0,0 +1,162 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SyncNextNeighborsNoGhosts.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#include "SyncNextNeighborsNoGhosts.h" + +#include <mesa_pd/mpi/RemoveAndNotify.h> + +namespace walberla { +namespace mesa_pd { +namespace mpi { + +void SyncNextNeighborsNoGhosts::operator()(data::ParticleStorage& ps, + const domain::IDomain& domain) const +{ + if (numProcesses_ == 1) return; + + neighborRanks_ = domain.getNeighborProcesses(); + for( uint_t nbProcessRank : neighborRanks_ ) + { + if (bs.sendBuffer(nbProcessRank).isEmpty()) + { + // fill empty buffers with a dummy byte to force transmission + bs.sendBuffer(nbProcessRank) << walberla::uint8_c(0); + } + } + generateSynchronizationMessages(ps, domain); + + // size of buffer is unknown and changes with each send + bs.setReceiverInfoFromSendBufferState(false, true); + bs.sendAll(); + + // Receiving the updates for the remote rigid bodies from the connected processes + WALBERLA_LOG_DETAIL( "Parsing of particle synchronization response starts..." ); + ParseMessage parseMessage; + for( auto it = bs.begin(); it != bs.end(); ++it ) + { + walberla::uint8_t tmp; + it.buffer() >> tmp; + while( !it.buffer().isEmpty() ) + { + parseMessage(it.rank(), it.buffer(), ps, domain); + } + } + WALBERLA_LOG_DETAIL( "Parsing of particle synchronization response ended." ); +} + +void SyncNextNeighborsNoGhosts::generateSynchronizationMessages(data::ParticleStorage& ps, + const domain::IDomain& domain) const +{ + const uint_t ownRank = uint_c(rank_); + + WALBERLA_LOG_DETAIL( "Assembling of particle synchronization message starts..." ); + + // position update + for( auto pIt = ps.begin(); pIt != ps.end(); ) + { + //skip all ghost particles + if (data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::GHOST)) + { + ++pIt; + continue; + } + + //skip all particles that do not communicate (create ghost particles) on other processes + if (data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::NON_COMMUNICATING)) + { + ++pIt; + continue; + } + + //correct position to make sure particle is always inside the domain! + //everything is decided by the master particle therefore ghost particles are not touched + if (!data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::FIXED) && + !data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::GHOST)) + { + domain.periodicallyMapToDomain( pIt->getPositionRef() ); + } + + // Note: At this point we know that the particle was locally owned before the position update. + WALBERLA_CHECK_EQUAL(pIt->getOwner(), ownRank); + + WALBERLA_LOG_DETAIL( "Processing local particle " << pIt->getUid() ); + + //particle has left subdomain? + const auto ownerRank = domain.findContainingProcessRank( pIt->getPosition() ); + if( ownerRank != int_c(ownRank) ) + { + WALBERLA_LOG_DETAIL( "Local particle " << pIt->getUid() << " is no longer on process " << ownRank << " but on process " << ownerRank ); + + if( ownerRank < 0 ) { + // No owner found: Outflow condition. + WALBERLA_LOG_DETAIL( "Sending deletion notifications for particle " << pIt->getUid() << " due to outflow." ); + + // remove particle + // since there are no ghosts owners no one has to be notified + pIt = ps.erase( pIt ); + + continue; + } + + // create ghost on new owner process + auto& buffer( bs.sendBuffer(ownerRank) ); + WALBERLA_LOG_DETAIL( "Sending ghost copy notification for particle " << pIt->getUid() << " to process " << ownerRank ); + packNotification(buffer, ParticleGhostCopyNotification( *pIt )); + + WALBERLA_LOG_DETAIL( "Sending migration notification for particle " << pIt->getUid() << " to process " << ownerRank << "." ); + //WALBERLA_LOG_DETAIL( "Process registration list before migration: " << pIt->getGhostOwners() ); + + // Set new owner and transform to ghost particle + pIt->setOwner(ownerRank); + data::particle_flags::set( pIt->getFlagsRef(), data::particle_flags::GHOST ); + + // currently position is mapped to periodically to global domain, + // this might not be the correct position for a ghost particle + domain.correctParticlePosition( pIt->getPositionRef() ); + + // Send migration notification to new owner + packNotification(buffer, ParticleMigrationNotification( *pIt )); + + //remove particle from local process + pIt = ps.erase( pIt ); + + continue; + + } else + { + // particle still is locally owned after position update. + WALBERLA_LOG_DETAIL( "Owner of particle " << pIt->getUid() << " is still process " << pIt->getOwner() ); + } + + ++pIt; + } + + WALBERLA_LOG_DETAIL( "Assembling of particle synchronization message ended." ); +} + +} // namespace mpi +} // namespace mesa_pd +} // namespace walberla diff --git a/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h new file mode 100644 index 000000000..7ffc5f2b7 --- /dev/null +++ b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h @@ -0,0 +1,81 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SyncNextNeighborsNoGhosts.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/Flags.h> +#include <mesa_pd/data/ParticleStorage.h> +#include <mesa_pd/domain/IDomain.h> +#include <mesa_pd/mpi/notifications/PackNotification.h> +#include <mesa_pd/mpi/notifications/ParseMessage.h> +#include <mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h> +#include <mesa_pd/mpi/notifications/ParticleMigrationNotification.h> +#include <mesa_pd/mpi/notifications/ParticleRemoteMigrationNotification.h> +#include <mesa_pd/mpi/notifications/ParticleRemovalNotification.h> +#include <mesa_pd/mpi/notifications/ParticleUpdateNotification.h> + +#include <core/mpi/BufferSystem.h> +#include <core/logging/Logging.h> + +namespace walberla { +namespace mesa_pd { +namespace mpi { + +/** + * Next neighbor synchronization kernel without ghost particles. + * + * This kernel conducts particle migrations if they move to another subdomain + * but does not generate ghost particles on overlap. This can be useful for + * particles without spatial extend like tracer particles. + * + * \ingroup mesa_pd_mpi + */ +class SyncNextNeighborsNoGhosts +{ +public: + void operator()(data::ParticleStorage& ps, + const domain::IDomain& domain) const; + + int64_t getBytesSent() const { return bs.getBytesSent(); } + int64_t getBytesReceived() const { return bs.getBytesReceived(); } + + int64_t getNumberOfSends() const { return bs.getNumberOfSends(); } + int64_t getNumberOfReceives() const { return bs.getNumberOfReceives(); } +private: + void generateSynchronizationMessages(data::ParticleStorage& ps, + const domain::IDomain& domain) const; + mutable std::vector<uint_t> neighborRanks_; ///cache for neighbor ranks -> will be updated in operator() + + mutable walberla::mpi::BufferSystem bs = walberla::mpi::BufferSystem( walberla::mpi::MPIManager::instance()->comm() ); + + int numProcesses_ = walberla::mpi::MPIManager::instance()->numProcesses(); + int rank_ = walberla::mpi::MPIManager::instance()->rank(); +}; + +} // namespace mpi +} // namespace mesa_pd +} // namespace walberla diff --git a/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h b/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h index 8da120f08..e1dce5b88 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h @@ -113,7 +113,7 @@ void ParseMessage::operator()(int sender, WALBERLA_CHECK(data::particle_flags::isSet(pIt->getFlags(), data::particle_flags::GHOST), "Update notification must only concern shadow copies."); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ALWAYS"] %} pIt->set{{prop.name | capFirst}}(objparam.{{prop.name}}); {%- endif %} @@ -144,7 +144,7 @@ void ParseMessage::operator()(int sender, pIt->setOwner(receiver_); data::particle_flags::unset(pIt->getFlagsRef(), data::particle_flags::GHOST); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_OWNERSHIP_CHANGE"] %} pIt->set{{prop.name | capFirst}}(objparam.{{prop.name}}_); {%- endif %} diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h index 505dfbccc..e2414008e 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h @@ -48,7 +48,7 @@ class ParticleCopyNotification public: struct Parameters { - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if not prop.syncMode == "NEVER" %} {{prop.type}} {{prop.name}} {{'{'}}{{prop.defValue}}{{'}'}}; {%- endif %} @@ -64,7 +64,7 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& WALBERLA_ASSERT_EQUAL(ps.find(data.uid), ps.end(), "Particle with same uid already existent!"); auto pIt = ps.create(data.uid); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if not prop.syncMode == "NEVER" %} pIt->set{{prop.name | capFirst}}(data.{{prop.name}}); {%- endif %} @@ -95,7 +95,7 @@ template< typename T, // Element type of SendBuffer mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, const mesa_pd::ParticleCopyNotification& obj ) { buf.addDebugMarker( "cn" ); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if not prop.syncMode == "NEVER" %} buf << obj.particle_.get{{prop.name | capFirst}}(); {%- endif %} @@ -107,7 +107,7 @@ template< typename T> // Element type of RecvBuffer mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd::ParticleCopyNotification::Parameters& objparam ) { buf.readDebugMarker( "cn" ); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if not prop.syncMode == "NEVER" %} buf >> objparam.{{prop.name}}; {%- endif %} diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h index 9fd397201..52dd0a780 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h @@ -48,7 +48,7 @@ class ParticleGhostCopyNotification public: struct Parameters { - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_GHOST_CREATION", "ALWAYS"] %} {{prop.type}} {{prop.name}} {{'{'}}{{prop.defValue}}{{'}'}}; {%- endif %} @@ -64,7 +64,7 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& WALBERLA_ASSERT_EQUAL(ps.find(data.uid), ps.end(), "Particle with same uid already existent!"); auto pIt = ps.create(data.uid); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_GHOST_CREATION", "ALWAYS"] %} pIt->set{{prop.name | capFirst}}(data.{{prop.name}}); {%- endif %} @@ -95,7 +95,7 @@ template< typename T, // Element type of SendBuffer mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, const mesa_pd::ParticleGhostCopyNotification& obj ) { buf.addDebugMarker( "cn" ); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_GHOST_CREATION", "ALWAYS"] %} buf << obj.particle_.get{{prop.name | capFirst}}(); {%- endif %} @@ -107,7 +107,7 @@ template< typename T> // Element type of RecvBuffer mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd::ParticleGhostCopyNotification::Parameters& objparam ) { buf.readDebugMarker( "cn" ); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_GHOST_CREATION", "ALWAYS"] %} buf >> objparam.{{prop.name}}; {%- endif %} diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h index 3ca6e41de..f478bcc9c 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h @@ -45,7 +45,7 @@ class ParticleMigrationNotification { public: struct Parameters { id_t uid_; - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_OWNERSHIP_CHANGE"] %} {{prop.type}} {{prop.name}}_ {{'{'}}{{prop.defValue}}{{'}'}}; {%- endif %} @@ -80,7 +80,7 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons { buf.addDebugMarker( "mn" ); buf << obj.particle_.getUid(); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_OWNERSHIP_CHANGE"] %} buf << obj.particle_.get{{prop.name | capFirst}}(); {%- endif %} @@ -93,7 +93,7 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: { buf.readDebugMarker( "mn" ); buf >> objparam.uid_; - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ON_OWNERSHIP_CHANGE"] %} buf >> objparam.{{prop.name}}_; {%- endif %} diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h index dd59c8217..507eeda47 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h @@ -45,7 +45,7 @@ namespace mesa_pd { class ParticleUpdateNotification { public: struct Parameters { - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ALWAYS"] %} {{prop.type}} {{prop.name}} {{'{'}}{{prop.defValue}}{{'}'}}; {%- endif %} @@ -79,7 +79,7 @@ template< typename T, // Element type of SendBuffer mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, const mesa_pd::ParticleUpdateNotification& obj ) { buf.addDebugMarker( "un" ); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ALWAYS"] %} buf << obj.particle_.get{{prop.name | capFirst}}(); {%- endif %} @@ -91,7 +91,7 @@ template< typename T> // Element type of RecvBuffer mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd::ParticleUpdateNotification::Parameters& objparam ) { buf.readDebugMarker( "un" ); - {%- for prop in properties %} + {%- for prop in particle.properties %} {%- if prop.syncMode in ["ALWAYS"] %} buf >> objparam.{{prop.name}}; {%- endif %} diff --git a/python/mesa_pd/utility.py b/python/mesa_pd/utility.py index eff810487..b5a86337d 100644 --- a/python/mesa_pd/utility.py +++ b/python/mesa_pd/utility.py @@ -3,42 +3,38 @@ from jinja2 import Environment, FileSystemLoader import os + class TerminalColor: - DEFAULT = '\033[0m' - GREEN = '\033[92m' - YELLOW = '\033[93m' - RED = '\033[91m' + DEFAULT = '\033[0m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + RED = '\033[91m' + def find(f, seq): - """Return first item in sequence where f(item) == True.""" - for item in seq: - if f(item): - return item - return None - -def capFirst(s): - return s[0].capitalize() + s[1:] - -def getJinjaEnvironment(): - dirname = os.path.dirname(__file__) - env = Environment(loader=FileSystemLoader(dirname + '/templates')) - env.filters['capFirst'] = capFirst - return env - -def checkInterface(path, template, accessor): - with open(path + template, 'r') as myfile: - data = myfile.read() - for prop in accessor.properties: - for func in prop.getFunctionNames(): - if not (func in data): - raise RuntimeError("{} required but not used in kernel ({})".format(func, template)) - -def generateFile(path, template, context = {}, filename=None): - if filename==None: - filename = template.replace(".templ", "") - env = getJinjaEnvironment() - print("generating: " + path + filename) - fout = open(path + filename, "wb") - content = env.get_template(template).render(context) - fout.write(content.encode('utf8')) - fout.close() + """Return first item in sequence where f(item) == True.""" + for item in seq: + if f(item): + return item + return None + + +def cap_first(s): + return s[0].capitalize() + s[1:] + + +def get_jinja_environment(): + dirname = os.path.dirname(__file__) + env = Environment(loader=FileSystemLoader(dirname + '/templates')) + env.filters['capFirst'] = cap_first + return env + + +def generate_file(path, template, context={}, filename=None): + if filename == None: + filename = template.replace(".templ", "") + env = get_jinja_environment() + print(f"generating: {(path / filename)}") + with open(path / filename, "wb") as fout: + content = env.get_template(template).render(context) + fout.write(content.encode('utf8')) diff --git a/src/mesa_pd/data/ParticleAccessor.h b/src/mesa_pd/data/ParticleAccessor.h index ebb81768e..59e575330 100644 --- a/src/mesa_pd/data/ParticleAccessor.h +++ b/src/mesa_pd/data/ParticleAccessor.h @@ -72,22 +72,6 @@ public: std::unordered_set<walberla::mpi::MPIRank>& getGhostOwnersRef(const size_t p_idx) {return ps_->getGhostOwnersRef(p_idx);} void setGhostOwners(const size_t p_idx, std::unordered_set<walberla::mpi::MPIRank> const & v) { ps_->setGhostOwners(p_idx, v);} - size_t const & getShapeID(const size_t p_idx) const {return ps_->getShapeID(p_idx);} - size_t& getShapeIDRef(const size_t p_idx) {return ps_->getShapeIDRef(p_idx);} - void setShapeID(const size_t p_idx, size_t const & v) { ps_->setShapeID(p_idx, v);} - - walberla::mesa_pd::Rot3 const & getRotation(const size_t p_idx) const {return ps_->getRotation(p_idx);} - walberla::mesa_pd::Rot3& getRotationRef(const size_t p_idx) {return ps_->getRotationRef(p_idx);} - void setRotation(const size_t p_idx, walberla::mesa_pd::Rot3 const & v) { ps_->setRotation(p_idx, v);} - - walberla::mesa_pd::Vec3 const & getAngularVelocity(const size_t p_idx) const {return ps_->getAngularVelocity(p_idx);} - walberla::mesa_pd::Vec3& getAngularVelocityRef(const size_t p_idx) {return ps_->getAngularVelocityRef(p_idx);} - void setAngularVelocity(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setAngularVelocity(p_idx, v);} - - walberla::mesa_pd::Vec3 const & getTorque(const size_t p_idx) const {return ps_->getTorque(p_idx);} - walberla::mesa_pd::Vec3& getTorqueRef(const size_t p_idx) {return ps_->getTorqueRef(p_idx);} - void setTorque(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setTorque(p_idx, v);} - walberla::mesa_pd::Vec3 const & getLinearVelocity(const size_t p_idx) const {return ps_->getLinearVelocity(p_idx);} walberla::mesa_pd::Vec3& getLinearVelocityRef(const size_t p_idx) {return ps_->getLinearVelocityRef(p_idx);} void setLinearVelocity(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setLinearVelocity(p_idx, v);} @@ -104,6 +88,22 @@ public: walberla::mesa_pd::Vec3& getOldForceRef(const size_t p_idx) {return ps_->getOldForceRef(p_idx);} void setOldForce(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setOldForce(p_idx, v);} + size_t const & getShapeID(const size_t p_idx) const {return ps_->getShapeID(p_idx);} + size_t& getShapeIDRef(const size_t p_idx) {return ps_->getShapeIDRef(p_idx);} + void setShapeID(const size_t p_idx, size_t const & v) { ps_->setShapeID(p_idx, v);} + + walberla::mesa_pd::Rot3 const & getRotation(const size_t p_idx) const {return ps_->getRotation(p_idx);} + walberla::mesa_pd::Rot3& getRotationRef(const size_t p_idx) {return ps_->getRotationRef(p_idx);} + void setRotation(const size_t p_idx, walberla::mesa_pd::Rot3 const & v) { ps_->setRotation(p_idx, v);} + + walberla::mesa_pd::Vec3 const & getAngularVelocity(const size_t p_idx) const {return ps_->getAngularVelocity(p_idx);} + walberla::mesa_pd::Vec3& getAngularVelocityRef(const size_t p_idx) {return ps_->getAngularVelocityRef(p_idx);} + void setAngularVelocity(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setAngularVelocity(p_idx, v);} + + walberla::mesa_pd::Vec3 const & getTorque(const size_t p_idx) const {return ps_->getTorque(p_idx);} + walberla::mesa_pd::Vec3& getTorqueRef(const size_t p_idx) {return ps_->getTorqueRef(p_idx);} + void setTorque(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setTorque(p_idx, v);} + walberla::mesa_pd::Vec3 const & getOldTorque(const size_t p_idx) const {return ps_->getOldTorque(p_idx);} walberla::mesa_pd::Vec3& getOldTorqueRef(const size_t p_idx) {return ps_->getOldTorqueRef(p_idx);} void setOldTorque(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setOldTorque(p_idx, v);} @@ -233,22 +233,6 @@ public: void setGhostOwners(const size_t /*p_idx*/, std::unordered_set<walberla::mpi::MPIRank> const & v) { ghostOwners_ = v;} std::unordered_set<walberla::mpi::MPIRank>& getGhostOwnersRef(const size_t /*p_idx*/) {return ghostOwners_;} - size_t const & getShapeID(const size_t /*p_idx*/) const {return shapeID_;} - void setShapeID(const size_t /*p_idx*/, size_t const & v) { shapeID_ = v;} - size_t& getShapeIDRef(const size_t /*p_idx*/) {return shapeID_;} - - walberla::mesa_pd::Rot3 const & getRotation(const size_t /*p_idx*/) const {return rotation_;} - void setRotation(const size_t /*p_idx*/, walberla::mesa_pd::Rot3 const & v) { rotation_ = v;} - walberla::mesa_pd::Rot3& getRotationRef(const size_t /*p_idx*/) {return rotation_;} - - walberla::mesa_pd::Vec3 const & getAngularVelocity(const size_t /*p_idx*/) const {return angularVelocity_;} - void setAngularVelocity(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { angularVelocity_ = v;} - walberla::mesa_pd::Vec3& getAngularVelocityRef(const size_t /*p_idx*/) {return angularVelocity_;} - - walberla::mesa_pd::Vec3 const & getTorque(const size_t /*p_idx*/) const {return torque_;} - void setTorque(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { torque_ = v;} - walberla::mesa_pd::Vec3& getTorqueRef(const size_t /*p_idx*/) {return torque_;} - walberla::mesa_pd::Vec3 const & getLinearVelocity(const size_t /*p_idx*/) const {return linearVelocity_;} void setLinearVelocity(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { linearVelocity_ = v;} walberla::mesa_pd::Vec3& getLinearVelocityRef(const size_t /*p_idx*/) {return linearVelocity_;} @@ -265,6 +249,22 @@ public: void setOldForce(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { oldForce_ = v;} walberla::mesa_pd::Vec3& getOldForceRef(const size_t /*p_idx*/) {return oldForce_;} + size_t const & getShapeID(const size_t /*p_idx*/) const {return shapeID_;} + void setShapeID(const size_t /*p_idx*/, size_t const & v) { shapeID_ = v;} + size_t& getShapeIDRef(const size_t /*p_idx*/) {return shapeID_;} + + walberla::mesa_pd::Rot3 const & getRotation(const size_t /*p_idx*/) const {return rotation_;} + void setRotation(const size_t /*p_idx*/, walberla::mesa_pd::Rot3 const & v) { rotation_ = v;} + walberla::mesa_pd::Rot3& getRotationRef(const size_t /*p_idx*/) {return rotation_;} + + walberla::mesa_pd::Vec3 const & getAngularVelocity(const size_t /*p_idx*/) const {return angularVelocity_;} + void setAngularVelocity(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { angularVelocity_ = v;} + walberla::mesa_pd::Vec3& getAngularVelocityRef(const size_t /*p_idx*/) {return angularVelocity_;} + + walberla::mesa_pd::Vec3 const & getTorque(const size_t /*p_idx*/) const {return torque_;} + void setTorque(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { torque_ = v;} + walberla::mesa_pd::Vec3& getTorqueRef(const size_t /*p_idx*/) {return torque_;} + walberla::mesa_pd::Vec3 const & getOldTorque(const size_t /*p_idx*/) const {return oldTorque_;} void setOldTorque(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { oldTorque_ = v;} walberla::mesa_pd::Vec3& getOldTorqueRef(const size_t /*p_idx*/) {return oldTorque_;} @@ -342,14 +342,14 @@ private: walberla::mesa_pd::data::particle_flags::FlagT flags_; int owner_; std::unordered_set<walberla::mpi::MPIRank> ghostOwners_; - size_t shapeID_; - walberla::mesa_pd::Rot3 rotation_; - walberla::mesa_pd::Vec3 angularVelocity_; - walberla::mesa_pd::Vec3 torque_; walberla::mesa_pd::Vec3 linearVelocity_; walberla::real_t invMass_; walberla::mesa_pd::Vec3 force_; walberla::mesa_pd::Vec3 oldForce_; + size_t shapeID_; + walberla::mesa_pd::Rot3 rotation_; + walberla::mesa_pd::Vec3 angularVelocity_; + walberla::mesa_pd::Vec3 torque_; walberla::mesa_pd::Vec3 oldTorque_; blockforest::BlockID currentBlock_; uint_t type_; diff --git a/src/mesa_pd/data/ParticleStorage.h b/src/mesa_pd/data/ParticleStorage.h index 53c157277..a22470d67 100644 --- a/src/mesa_pd/data/ParticleStorage.h +++ b/src/mesa_pd/data/ParticleStorage.h @@ -77,14 +77,14 @@ public: using flags_type = walberla::mesa_pd::data::particle_flags::FlagT; using owner_type = int; using ghostOwners_type = std::unordered_set<walberla::mpi::MPIRank>; - using shapeID_type = size_t; - using rotation_type = walberla::mesa_pd::Rot3; - using angularVelocity_type = walberla::mesa_pd::Vec3; - using torque_type = walberla::mesa_pd::Vec3; using linearVelocity_type = walberla::mesa_pd::Vec3; using invMass_type = walberla::real_t; using force_type = walberla::mesa_pd::Vec3; using oldForce_type = walberla::mesa_pd::Vec3; + using shapeID_type = size_t; + using rotation_type = walberla::mesa_pd::Rot3; + using angularVelocity_type = walberla::mesa_pd::Vec3; + using torque_type = walberla::mesa_pd::Vec3; using oldTorque_type = walberla::mesa_pd::Vec3; using currentBlock_type = blockforest::BlockID; using type_type = uint_t; @@ -126,22 +126,6 @@ public: ghostOwners_type& getGhostOwnersRef() {return storage_.getGhostOwnersRef(i_);} void setGhostOwners(ghostOwners_type const & v) { storage_.setGhostOwners(i_, v);} - shapeID_type const & getShapeID() const {return storage_.getShapeID(i_);} - shapeID_type& getShapeIDRef() {return storage_.getShapeIDRef(i_);} - void setShapeID(shapeID_type const & v) { storage_.setShapeID(i_, v);} - - rotation_type const & getRotation() const {return storage_.getRotation(i_);} - rotation_type& getRotationRef() {return storage_.getRotationRef(i_);} - void setRotation(rotation_type const & v) { storage_.setRotation(i_, v);} - - angularVelocity_type const & getAngularVelocity() const {return storage_.getAngularVelocity(i_);} - angularVelocity_type& getAngularVelocityRef() {return storage_.getAngularVelocityRef(i_);} - void setAngularVelocity(angularVelocity_type const & v) { storage_.setAngularVelocity(i_, v);} - - torque_type const & getTorque() const {return storage_.getTorque(i_);} - torque_type& getTorqueRef() {return storage_.getTorqueRef(i_);} - void setTorque(torque_type const & v) { storage_.setTorque(i_, v);} - linearVelocity_type const & getLinearVelocity() const {return storage_.getLinearVelocity(i_);} linearVelocity_type& getLinearVelocityRef() {return storage_.getLinearVelocityRef(i_);} void setLinearVelocity(linearVelocity_type const & v) { storage_.setLinearVelocity(i_, v);} @@ -158,6 +142,22 @@ public: oldForce_type& getOldForceRef() {return storage_.getOldForceRef(i_);} void setOldForce(oldForce_type const & v) { storage_.setOldForce(i_, v);} + shapeID_type const & getShapeID() const {return storage_.getShapeID(i_);} + shapeID_type& getShapeIDRef() {return storage_.getShapeIDRef(i_);} + void setShapeID(shapeID_type const & v) { storage_.setShapeID(i_, v);} + + rotation_type const & getRotation() const {return storage_.getRotation(i_);} + rotation_type& getRotationRef() {return storage_.getRotationRef(i_);} + void setRotation(rotation_type const & v) { storage_.setRotation(i_, v);} + + angularVelocity_type const & getAngularVelocity() const {return storage_.getAngularVelocity(i_);} + angularVelocity_type& getAngularVelocityRef() {return storage_.getAngularVelocityRef(i_);} + void setAngularVelocity(angularVelocity_type const & v) { storage_.setAngularVelocity(i_, v);} + + torque_type const & getTorque() const {return storage_.getTorque(i_);} + torque_type& getTorqueRef() {return storage_.getTorqueRef(i_);} + void setTorque(torque_type const & v) { storage_.setTorque(i_, v);} + oldTorque_type const & getOldTorque() const {return storage_.getOldTorque(i_);} oldTorque_type& getOldTorqueRef() {return storage_.getOldTorqueRef(i_);} void setOldTorque(oldTorque_type const & v) { storage_.setOldTorque(i_, v);} @@ -284,14 +284,14 @@ public: using flags_type = walberla::mesa_pd::data::particle_flags::FlagT; using owner_type = int; using ghostOwners_type = std::unordered_set<walberla::mpi::MPIRank>; - using shapeID_type = size_t; - using rotation_type = walberla::mesa_pd::Rot3; - using angularVelocity_type = walberla::mesa_pd::Vec3; - using torque_type = walberla::mesa_pd::Vec3; using linearVelocity_type = walberla::mesa_pd::Vec3; using invMass_type = walberla::real_t; using force_type = walberla::mesa_pd::Vec3; using oldForce_type = walberla::mesa_pd::Vec3; + using shapeID_type = size_t; + using rotation_type = walberla::mesa_pd::Rot3; + using angularVelocity_type = walberla::mesa_pd::Vec3; + using torque_type = walberla::mesa_pd::Vec3; using oldTorque_type = walberla::mesa_pd::Vec3; using currentBlock_type = blockforest::BlockID; using type_type = uint_t; @@ -333,22 +333,6 @@ public: ghostOwners_type& getGhostOwnersRef(const size_t idx) {return ghostOwners_[idx];} void setGhostOwners(const size_t idx, ghostOwners_type const & v) { ghostOwners_[idx] = v; } - shapeID_type const & getShapeID(const size_t idx) const {return shapeID_[idx];} - shapeID_type& getShapeIDRef(const size_t idx) {return shapeID_[idx];} - void setShapeID(const size_t idx, shapeID_type const & v) { shapeID_[idx] = v; } - - rotation_type const & getRotation(const size_t idx) const {return rotation_[idx];} - rotation_type& getRotationRef(const size_t idx) {return rotation_[idx];} - void setRotation(const size_t idx, rotation_type const & v) { rotation_[idx] = v; } - - angularVelocity_type const & getAngularVelocity(const size_t idx) const {return angularVelocity_[idx];} - angularVelocity_type& getAngularVelocityRef(const size_t idx) {return angularVelocity_[idx];} - void setAngularVelocity(const size_t idx, angularVelocity_type const & v) { angularVelocity_[idx] = v; } - - torque_type const & getTorque(const size_t idx) const {return torque_[idx];} - torque_type& getTorqueRef(const size_t idx) {return torque_[idx];} - void setTorque(const size_t idx, torque_type const & v) { torque_[idx] = v; } - linearVelocity_type const & getLinearVelocity(const size_t idx) const {return linearVelocity_[idx];} linearVelocity_type& getLinearVelocityRef(const size_t idx) {return linearVelocity_[idx];} void setLinearVelocity(const size_t idx, linearVelocity_type const & v) { linearVelocity_[idx] = v; } @@ -365,6 +349,22 @@ public: oldForce_type& getOldForceRef(const size_t idx) {return oldForce_[idx];} void setOldForce(const size_t idx, oldForce_type const & v) { oldForce_[idx] = v; } + shapeID_type const & getShapeID(const size_t idx) const {return shapeID_[idx];} + shapeID_type& getShapeIDRef(const size_t idx) {return shapeID_[idx];} + void setShapeID(const size_t idx, shapeID_type const & v) { shapeID_[idx] = v; } + + rotation_type const & getRotation(const size_t idx) const {return rotation_[idx];} + rotation_type& getRotationRef(const size_t idx) {return rotation_[idx];} + void setRotation(const size_t idx, rotation_type const & v) { rotation_[idx] = v; } + + angularVelocity_type const & getAngularVelocity(const size_t idx) const {return angularVelocity_[idx];} + angularVelocity_type& getAngularVelocityRef(const size_t idx) {return angularVelocity_[idx];} + void setAngularVelocity(const size_t idx, angularVelocity_type const & v) { angularVelocity_[idx] = v; } + + torque_type const & getTorque(const size_t idx) const {return torque_[idx];} + torque_type& getTorqueRef(const size_t idx) {return torque_[idx];} + void setTorque(const size_t idx, torque_type const & v) { torque_[idx] = v; } + oldTorque_type const & getOldTorque(const size_t idx) const {return oldTorque_[idx];} oldTorque_type& getOldTorqueRef(const size_t idx) {return oldTorque_[idx];} void setOldTorque(const size_t idx, oldTorque_type const & v) { oldTorque_[idx] = v; } @@ -522,14 +522,14 @@ public: std::vector<flags_type> flags_ {}; std::vector<owner_type> owner_ {}; std::vector<ghostOwners_type> ghostOwners_ {}; - std::vector<shapeID_type> shapeID_ {}; - std::vector<rotation_type> rotation_ {}; - std::vector<angularVelocity_type> angularVelocity_ {}; - std::vector<torque_type> torque_ {}; std::vector<linearVelocity_type> linearVelocity_ {}; std::vector<invMass_type> invMass_ {}; std::vector<force_type> force_ {}; std::vector<oldForce_type> oldForce_ {}; + std::vector<shapeID_type> shapeID_ {}; + std::vector<rotation_type> rotation_ {}; + std::vector<angularVelocity_type> angularVelocity_ {}; + std::vector<torque_type> torque_ {}; std::vector<oldTorque_type> oldTorque_ {}; std::vector<currentBlock_type> currentBlock_ {}; std::vector<type_type> type_ {}; @@ -560,14 +560,14 @@ ParticleStorage::Particle& ParticleStorage::Particle::operator=(const ParticleSt getFlagsRef() = rhs.getFlags(); getOwnerRef() = rhs.getOwner(); getGhostOwnersRef() = rhs.getGhostOwners(); - getShapeIDRef() = rhs.getShapeID(); - getRotationRef() = rhs.getRotation(); - getAngularVelocityRef() = rhs.getAngularVelocity(); - getTorqueRef() = rhs.getTorque(); getLinearVelocityRef() = rhs.getLinearVelocity(); getInvMassRef() = rhs.getInvMass(); getForceRef() = rhs.getForce(); getOldForceRef() = rhs.getOldForce(); + getShapeIDRef() = rhs.getShapeID(); + getRotationRef() = rhs.getRotation(); + getAngularVelocityRef() = rhs.getAngularVelocity(); + getTorqueRef() = rhs.getTorque(); getOldTorqueRef() = rhs.getOldTorque(); getCurrentBlockRef() = rhs.getCurrentBlock(); getTypeRef() = rhs.getType(); @@ -595,14 +595,14 @@ ParticleStorage::Particle& ParticleStorage::Particle::operator=(ParticleStorage: getFlagsRef() = std::move(rhs.getFlagsRef()); getOwnerRef() = std::move(rhs.getOwnerRef()); getGhostOwnersRef() = std::move(rhs.getGhostOwnersRef()); - getShapeIDRef() = std::move(rhs.getShapeIDRef()); - getRotationRef() = std::move(rhs.getRotationRef()); - getAngularVelocityRef() = std::move(rhs.getAngularVelocityRef()); - getTorqueRef() = std::move(rhs.getTorqueRef()); getLinearVelocityRef() = std::move(rhs.getLinearVelocityRef()); getInvMassRef() = std::move(rhs.getInvMassRef()); getForceRef() = std::move(rhs.getForceRef()); getOldForceRef() = std::move(rhs.getOldForceRef()); + getShapeIDRef() = std::move(rhs.getShapeIDRef()); + getRotationRef() = std::move(rhs.getRotationRef()); + getAngularVelocityRef() = std::move(rhs.getAngularVelocityRef()); + getTorqueRef() = std::move(rhs.getTorqueRef()); getOldTorqueRef() = std::move(rhs.getOldTorqueRef()); getCurrentBlockRef() = std::move(rhs.getCurrentBlockRef()); getTypeRef() = std::move(rhs.getTypeRef()); @@ -631,14 +631,14 @@ void swap(ParticleStorage::Particle lhs, ParticleStorage::Particle rhs) std::swap(lhs.getFlagsRef(), rhs.getFlagsRef()); std::swap(lhs.getOwnerRef(), rhs.getOwnerRef()); std::swap(lhs.getGhostOwnersRef(), rhs.getGhostOwnersRef()); - std::swap(lhs.getShapeIDRef(), rhs.getShapeIDRef()); - std::swap(lhs.getRotationRef(), rhs.getRotationRef()); - std::swap(lhs.getAngularVelocityRef(), rhs.getAngularVelocityRef()); - std::swap(lhs.getTorqueRef(), rhs.getTorqueRef()); std::swap(lhs.getLinearVelocityRef(), rhs.getLinearVelocityRef()); std::swap(lhs.getInvMassRef(), rhs.getInvMassRef()); std::swap(lhs.getForceRef(), rhs.getForceRef()); std::swap(lhs.getOldForceRef(), rhs.getOldForceRef()); + std::swap(lhs.getShapeIDRef(), rhs.getShapeIDRef()); + std::swap(lhs.getRotationRef(), rhs.getRotationRef()); + std::swap(lhs.getAngularVelocityRef(), rhs.getAngularVelocityRef()); + std::swap(lhs.getTorqueRef(), rhs.getTorqueRef()); std::swap(lhs.getOldTorqueRef(), rhs.getOldTorqueRef()); std::swap(lhs.getCurrentBlockRef(), rhs.getCurrentBlockRef()); std::swap(lhs.getTypeRef(), rhs.getTypeRef()); @@ -667,14 +667,14 @@ std::ostream& operator<<( std::ostream& os, const ParticleStorage::Particle& p ) "flags : " << p.getFlags() << "\n" << "owner : " << p.getOwner() << "\n" << "ghostOwners : " << p.getGhostOwners() << "\n" << - "shapeID : " << p.getShapeID() << "\n" << - "rotation : " << p.getRotation() << "\n" << - "angularVelocity : " << p.getAngularVelocity() << "\n" << - "torque : " << p.getTorque() << "\n" << "linearVelocity : " << p.getLinearVelocity() << "\n" << "invMass : " << p.getInvMass() << "\n" << "force : " << p.getForce() << "\n" << "oldForce : " << p.getOldForce() << "\n" << + "shapeID : " << p.getShapeID() << "\n" << + "rotation : " << p.getRotation() << "\n" << + "angularVelocity : " << p.getAngularVelocity() << "\n" << + "torque : " << p.getTorque() << "\n" << "oldTorque : " << p.getOldTorque() << "\n" << "currentBlock : " << p.getCurrentBlock() << "\n" << "type : " << p.getType() << "\n" << @@ -773,14 +773,14 @@ inline ParticleStorage::iterator ParticleStorage::create(const id_t& uid) flags_.emplace_back(); owner_.emplace_back(-1); ghostOwners_.emplace_back(); - shapeID_.emplace_back(); - rotation_.emplace_back(); - angularVelocity_.emplace_back(real_t(0)); - torque_.emplace_back(real_t(0)); linearVelocity_.emplace_back(real_t(0)); invMass_.emplace_back(real_t(1)); force_.emplace_back(real_t(0)); oldForce_.emplace_back(real_t(0)); + shapeID_.emplace_back(); + rotation_.emplace_back(); + angularVelocity_.emplace_back(real_t(0)); + torque_.emplace_back(real_t(0)); oldTorque_.emplace_back(real_t(0)); currentBlock_.emplace_back(); type_.emplace_back(0); @@ -834,14 +834,14 @@ inline ParticleStorage::iterator ParticleStorage::erase(iterator& it) flags_.pop_back(); owner_.pop_back(); ghostOwners_.pop_back(); - shapeID_.pop_back(); - rotation_.pop_back(); - angularVelocity_.pop_back(); - torque_.pop_back(); linearVelocity_.pop_back(); invMass_.pop_back(); force_.pop_back(); oldForce_.pop_back(); + shapeID_.pop_back(); + rotation_.pop_back(); + angularVelocity_.pop_back(); + torque_.pop_back(); oldTorque_.pop_back(); currentBlock_.pop_back(); type_.pop_back(); @@ -882,14 +882,14 @@ inline void ParticleStorage::reserve(const size_t size) flags_.reserve(size); owner_.reserve(size); ghostOwners_.reserve(size); - shapeID_.reserve(size); - rotation_.reserve(size); - angularVelocity_.reserve(size); - torque_.reserve(size); linearVelocity_.reserve(size); invMass_.reserve(size); force_.reserve(size); oldForce_.reserve(size); + shapeID_.reserve(size); + rotation_.reserve(size); + angularVelocity_.reserve(size); + torque_.reserve(size); oldTorque_.reserve(size); currentBlock_.reserve(size); type_.reserve(size); @@ -915,14 +915,14 @@ inline void ParticleStorage::clear() flags_.clear(); owner_.clear(); ghostOwners_.clear(); - shapeID_.clear(); - rotation_.clear(); - angularVelocity_.clear(); - torque_.clear(); linearVelocity_.clear(); invMass_.clear(); force_.clear(); oldForce_.clear(); + shapeID_.clear(); + rotation_.clear(); + angularVelocity_.clear(); + torque_.clear(); oldTorque_.clear(); currentBlock_.clear(); type_.clear(); @@ -949,14 +949,14 @@ inline size_t ParticleStorage::size() const //WALBERLA_ASSERT_EQUAL( uid_.size(), flags.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), owner.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), ghostOwners.size() ); - //WALBERLA_ASSERT_EQUAL( uid_.size(), shapeID.size() ); - //WALBERLA_ASSERT_EQUAL( uid_.size(), rotation.size() ); - //WALBERLA_ASSERT_EQUAL( uid_.size(), angularVelocity.size() ); - //WALBERLA_ASSERT_EQUAL( uid_.size(), torque.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), linearVelocity.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), invMass.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), force.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), oldForce.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), shapeID.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), rotation.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), angularVelocity.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), torque.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), oldTorque.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), currentBlock.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), type.size() ); @@ -1210,42 +1210,6 @@ public: std::unordered_set<walberla::mpi::MPIRank> const & operator()(const data::Particle& p) const {return p.getGhostOwners();} }; ///Predicate that selects a certain property from a Particle -class SelectParticleShapeID -{ -public: - using return_type = size_t; - size_t& operator()(data::Particle& p) const {return p.getShapeIDRef();} - size_t& operator()(data::Particle&& p) const {return p.getShapeIDRef();} - size_t const & operator()(const data::Particle& p) const {return p.getShapeID();} -}; -///Predicate that selects a certain property from a Particle -class SelectParticleRotation -{ -public: - using return_type = walberla::mesa_pd::Rot3; - walberla::mesa_pd::Rot3& operator()(data::Particle& p) const {return p.getRotationRef();} - walberla::mesa_pd::Rot3& operator()(data::Particle&& p) const {return p.getRotationRef();} - walberla::mesa_pd::Rot3 const & operator()(const data::Particle& p) const {return p.getRotation();} -}; -///Predicate that selects a certain property from a Particle -class SelectParticleAngularVelocity -{ -public: - using return_type = walberla::mesa_pd::Vec3; - walberla::mesa_pd::Vec3& operator()(data::Particle& p) const {return p.getAngularVelocityRef();} - walberla::mesa_pd::Vec3& operator()(data::Particle&& p) const {return p.getAngularVelocityRef();} - walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getAngularVelocity();} -}; -///Predicate that selects a certain property from a Particle -class SelectParticleTorque -{ -public: - using return_type = walberla::mesa_pd::Vec3; - walberla::mesa_pd::Vec3& operator()(data::Particle& p) const {return p.getTorqueRef();} - walberla::mesa_pd::Vec3& operator()(data::Particle&& p) const {return p.getTorqueRef();} - walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getTorque();} -}; -///Predicate that selects a certain property from a Particle class SelectParticleLinearVelocity { public: @@ -1282,6 +1246,42 @@ public: walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getOldForce();} }; ///Predicate that selects a certain property from a Particle +class SelectParticleShapeID +{ +public: + using return_type = size_t; + size_t& operator()(data::Particle& p) const {return p.getShapeIDRef();} + size_t& operator()(data::Particle&& p) const {return p.getShapeIDRef();} + size_t const & operator()(const data::Particle& p) const {return p.getShapeID();} +}; +///Predicate that selects a certain property from a Particle +class SelectParticleRotation +{ +public: + using return_type = walberla::mesa_pd::Rot3; + walberla::mesa_pd::Rot3& operator()(data::Particle& p) const {return p.getRotationRef();} + walberla::mesa_pd::Rot3& operator()(data::Particle&& p) const {return p.getRotationRef();} + walberla::mesa_pd::Rot3 const & operator()(const data::Particle& p) const {return p.getRotation();} +}; +///Predicate that selects a certain property from a Particle +class SelectParticleAngularVelocity +{ +public: + using return_type = walberla::mesa_pd::Vec3; + walberla::mesa_pd::Vec3& operator()(data::Particle& p) const {return p.getAngularVelocityRef();} + walberla::mesa_pd::Vec3& operator()(data::Particle&& p) const {return p.getAngularVelocityRef();} + walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getAngularVelocity();} +}; +///Predicate that selects a certain property from a Particle +class SelectParticleTorque +{ +public: + using return_type = walberla::mesa_pd::Vec3; + walberla::mesa_pd::Vec3& operator()(data::Particle& p) const {return p.getTorqueRef();} + walberla::mesa_pd::Vec3& operator()(data::Particle&& p) const {return p.getTorqueRef();} + walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getTorque();} +}; +///Predicate that selects a certain property from a Particle class SelectParticleOldTorque { public: diff --git a/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp new file mode 100644 index 000000000..cfd313cef --- /dev/null +++ b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp @@ -0,0 +1,162 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SyncNextNeighborsNoGhosts.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#include "SyncNextNeighborsNoGhosts.h" + +#include <mesa_pd/mpi/RemoveAndNotify.h> + +namespace walberla { +namespace mesa_pd { +namespace mpi { + +void SyncNextNeighborsNoGhosts::operator()(data::ParticleStorage& ps, + const domain::IDomain& domain) const +{ + if (numProcesses_ == 1) return; + + neighborRanks_ = domain.getNeighborProcesses(); + for( uint_t nbProcessRank : neighborRanks_ ) + { + if (bs.sendBuffer(nbProcessRank).isEmpty()) + { + // fill empty buffers with a dummy byte to force transmission + bs.sendBuffer(nbProcessRank) << walberla::uint8_c(0); + } + } + generateSynchronizationMessages(ps, domain); + + // size of buffer is unknown and changes with each send + bs.setReceiverInfoFromSendBufferState(false, true); + bs.sendAll(); + + // Receiving the updates for the remote rigid bodies from the connected processes + WALBERLA_LOG_DETAIL( "Parsing of particle synchronization response starts..." ); + ParseMessage parseMessage; + for( auto it = bs.begin(); it != bs.end(); ++it ) + { + walberla::uint8_t tmp; + it.buffer() >> tmp; + while( !it.buffer().isEmpty() ) + { + parseMessage(it.rank(), it.buffer(), ps, domain); + } + } + WALBERLA_LOG_DETAIL( "Parsing of particle synchronization response ended." ); +} + +void SyncNextNeighborsNoGhosts::generateSynchronizationMessages(data::ParticleStorage& ps, + const domain::IDomain& domain) const +{ + const uint_t ownRank = uint_c(rank_); + + WALBERLA_LOG_DETAIL( "Assembling of particle synchronization message starts..." ); + + // position update + for( auto pIt = ps.begin(); pIt != ps.end(); ) + { + //skip all ghost particles + if (data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::GHOST)) + { + ++pIt; + continue; + } + + //skip all particles that do not communicate (create ghost particles) on other processes + if (data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::NON_COMMUNICATING)) + { + ++pIt; + continue; + } + + //correct position to make sure particle is always inside the domain! + //everything is decided by the master particle therefore ghost particles are not touched + if (!data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::FIXED) && + !data::particle_flags::isSet( pIt->getFlags(), data::particle_flags::GHOST)) + { + domain.periodicallyMapToDomain( pIt->getPositionRef() ); + } + + // Note: At this point we know that the particle was locally owned before the position update. + WALBERLA_CHECK_EQUAL(pIt->getOwner(), ownRank); + + WALBERLA_LOG_DETAIL( "Processing local particle " << pIt->getUid() ); + + //particle has left subdomain? + const auto ownerRank = domain.findContainingProcessRank( pIt->getPosition() ); + if( ownerRank != int_c(ownRank) ) + { + WALBERLA_LOG_DETAIL( "Local particle " << pIt->getUid() << " is no longer on process " << ownRank << " but on process " << ownerRank ); + + if( ownerRank < 0 ) { + // No owner found: Outflow condition. + WALBERLA_LOG_DETAIL( "Sending deletion notifications for particle " << pIt->getUid() << " due to outflow." ); + + // remove particle + // since there are no ghosts owners no one has to be notified + pIt = ps.erase( pIt ); + + continue; + } + + // create ghost on new owner process + auto& buffer( bs.sendBuffer(ownerRank) ); + WALBERLA_LOG_DETAIL( "Sending ghost copy notification for particle " << pIt->getUid() << " to process " << ownerRank ); + packNotification(buffer, ParticleGhostCopyNotification( *pIt )); + + WALBERLA_LOG_DETAIL( "Sending migration notification for particle " << pIt->getUid() << " to process " << ownerRank << "." ); + //WALBERLA_LOG_DETAIL( "Process registration list before migration: " << pIt->getGhostOwners() ); + + // Set new owner and transform to ghost particle + pIt->setOwner(ownerRank); + data::particle_flags::set( pIt->getFlagsRef(), data::particle_flags::GHOST ); + + // currently position is mapped to periodically to global domain, + // this might not be the correct position for a ghost particle + domain.correctParticlePosition( pIt->getPositionRef() ); + + // Send migration notification to new owner + packNotification(buffer, ParticleMigrationNotification( *pIt )); + + //remove particle from local process + pIt = ps.erase( pIt ); + + continue; + + } else + { + // particle still is locally owned after position update. + WALBERLA_LOG_DETAIL( "Owner of particle " << pIt->getUid() << " is still process " << pIt->getOwner() ); + } + + ++pIt; + } + + WALBERLA_LOG_DETAIL( "Assembling of particle synchronization message ended." ); +} + +} // namespace mpi +} // namespace mesa_pd +} // namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h new file mode 100644 index 000000000..a802fe4d6 --- /dev/null +++ b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h @@ -0,0 +1,81 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SyncNextNeighborsNoGhosts.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/Flags.h> +#include <mesa_pd/data/ParticleStorage.h> +#include <mesa_pd/domain/IDomain.h> +#include <mesa_pd/mpi/notifications/PackNotification.h> +#include <mesa_pd/mpi/notifications/ParseMessage.h> +#include <mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h> +#include <mesa_pd/mpi/notifications/ParticleMigrationNotification.h> +#include <mesa_pd/mpi/notifications/ParticleRemoteMigrationNotification.h> +#include <mesa_pd/mpi/notifications/ParticleRemovalNotification.h> +#include <mesa_pd/mpi/notifications/ParticleUpdateNotification.h> + +#include <core/mpi/BufferSystem.h> +#include <core/logging/Logging.h> + +namespace walberla { +namespace mesa_pd { +namespace mpi { + +/** + * Next neighbor synchronization kernel without ghost particles. + * + * This kernel conducts particle migrations if they move to another subdomain + * but does not generate ghost particles on overlap. This can be useful for + * particles without spatial extend like tracer particles. + * + * \ingroup mesa_pd_mpi + */ +class SyncNextNeighborsNoGhosts +{ +public: + void operator()(data::ParticleStorage& ps, + const domain::IDomain& domain) const; + + int64_t getBytesSent() const { return bs.getBytesSent(); } + int64_t getBytesReceived() const { return bs.getBytesReceived(); } + + int64_t getNumberOfSends() const { return bs.getNumberOfSends(); } + int64_t getNumberOfReceives() const { return bs.getNumberOfReceives(); } +private: + void generateSynchronizationMessages(data::ParticleStorage& ps, + const domain::IDomain& domain) const; + mutable std::vector<uint_t> neighborRanks_; ///cache for neighbor ranks -> will be updated in operator() + + mutable walberla::mpi::BufferSystem bs = walberla::mpi::BufferSystem( walberla::mpi::MPIManager::instance()->comm() ); + + int numProcesses_ = walberla::mpi::MPIManager::instance()->numProcesses(); + int rank_ = walberla::mpi::MPIManager::instance()->rank(); +}; + +} // namespace mpi +} // namespace mesa_pd +} // namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/mpi/notifications/ParseMessage.h b/src/mesa_pd/mpi/notifications/ParseMessage.h index b865c131e..1794965c0 100644 --- a/src/mesa_pd/mpi/notifications/ParseMessage.h +++ b/src/mesa_pd/mpi/notifications/ParseMessage.h @@ -114,9 +114,9 @@ void ParseMessage::operator()(int sender, "Update notification must only concern shadow copies."); pIt->setUid(objparam.uid); pIt->setPosition(objparam.position); + pIt->setLinearVelocity(objparam.linearVelocity); pIt->setRotation(objparam.rotation); pIt->setAngularVelocity(objparam.angularVelocity); - pIt->setLinearVelocity(objparam.linearVelocity); pIt->setOldContactHistory(objparam.oldContactHistory); pIt->setTemperature(objparam.temperature); diff --git a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h index aa47b020b..1d9ca382c 100644 --- a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h @@ -54,12 +54,12 @@ public: walberla::mesa_pd::data::particle_flags::FlagT flags {}; int owner {-1}; std::unordered_set<walberla::mpi::MPIRank> ghostOwners {}; - size_t shapeID {}; - walberla::mesa_pd::Rot3 rotation {}; - walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; walberla::mesa_pd::Vec3 linearVelocity {real_t(0)}; walberla::real_t invMass {real_t(1)}; walberla::mesa_pd::Vec3 oldForce {real_t(0)}; + size_t shapeID {}; + walberla::mesa_pd::Rot3 rotation {}; + walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; walberla::mesa_pd::Vec3 oldTorque {real_t(0)}; uint_t type {0}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; @@ -81,12 +81,12 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& pIt->setFlags(data.flags); pIt->setOwner(data.owner); pIt->setGhostOwners(data.ghostOwners); - pIt->setShapeID(data.shapeID); - pIt->setRotation(data.rotation); - pIt->setAngularVelocity(data.angularVelocity); pIt->setLinearVelocity(data.linearVelocity); pIt->setInvMass(data.invMass); pIt->setOldForce(data.oldForce); + pIt->setShapeID(data.shapeID); + pIt->setRotation(data.rotation); + pIt->setAngularVelocity(data.angularVelocity); pIt->setOldTorque(data.oldTorque); pIt->setType(data.type); pIt->setOldContactHistory(data.oldContactHistory); @@ -123,12 +123,12 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getFlags(); buf << obj.particle_.getOwner(); buf << obj.particle_.getGhostOwners(); - buf << obj.particle_.getShapeID(); - buf << obj.particle_.getRotation(); - buf << obj.particle_.getAngularVelocity(); buf << obj.particle_.getLinearVelocity(); buf << obj.particle_.getInvMass(); buf << obj.particle_.getOldForce(); + buf << obj.particle_.getShapeID(); + buf << obj.particle_.getRotation(); + buf << obj.particle_.getAngularVelocity(); buf << obj.particle_.getOldTorque(); buf << obj.particle_.getType(); buf << obj.particle_.getOldContactHistory(); @@ -146,12 +146,12 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.flags; buf >> objparam.owner; buf >> objparam.ghostOwners; - buf >> objparam.shapeID; - buf >> objparam.rotation; - buf >> objparam.angularVelocity; buf >> objparam.linearVelocity; buf >> objparam.invMass; buf >> objparam.oldForce; + buf >> objparam.shapeID; + buf >> objparam.rotation; + buf >> objparam.angularVelocity; buf >> objparam.oldTorque; buf >> objparam.type; buf >> objparam.oldContactHistory; diff --git a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h index 0b8265c6f..ca769b85c 100644 --- a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h @@ -53,11 +53,11 @@ public: walberla::real_t interactionRadius {real_t(0)}; walberla::mesa_pd::data::particle_flags::FlagT flags {}; int owner {-1}; + walberla::mesa_pd::Vec3 linearVelocity {real_t(0)}; + walberla::real_t invMass {real_t(1)}; size_t shapeID {}; walberla::mesa_pd::Rot3 rotation {}; walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; - walberla::mesa_pd::Vec3 linearVelocity {real_t(0)}; - walberla::real_t invMass {real_t(1)}; uint_t type {0}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; walberla::real_t temperature {real_t(0)}; @@ -77,11 +77,11 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& pIt->setInteractionRadius(data.interactionRadius); pIt->setFlags(data.flags); pIt->setOwner(data.owner); + pIt->setLinearVelocity(data.linearVelocity); + pIt->setInvMass(data.invMass); pIt->setShapeID(data.shapeID); pIt->setRotation(data.rotation); pIt->setAngularVelocity(data.angularVelocity); - pIt->setLinearVelocity(data.linearVelocity); - pIt->setInvMass(data.invMass); pIt->setType(data.type); pIt->setOldContactHistory(data.oldContactHistory); pIt->setTemperature(data.temperature); @@ -116,11 +116,11 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getInteractionRadius(); buf << obj.particle_.getFlags(); buf << obj.particle_.getOwner(); + buf << obj.particle_.getLinearVelocity(); + buf << obj.particle_.getInvMass(); buf << obj.particle_.getShapeID(); buf << obj.particle_.getRotation(); buf << obj.particle_.getAngularVelocity(); - buf << obj.particle_.getLinearVelocity(); - buf << obj.particle_.getInvMass(); buf << obj.particle_.getType(); buf << obj.particle_.getOldContactHistory(); buf << obj.particle_.getTemperature(); @@ -136,11 +136,11 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.interactionRadius; buf >> objparam.flags; buf >> objparam.owner; + buf >> objparam.linearVelocity; + buf >> objparam.invMass; buf >> objparam.shapeID; buf >> objparam.rotation; buf >> objparam.angularVelocity; - buf >> objparam.linearVelocity; - buf >> objparam.invMass; buf >> objparam.type; buf >> objparam.oldContactHistory; buf >> objparam.temperature; diff --git a/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h b/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h index 5fdd625c1..62d0c6da3 100644 --- a/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h @@ -47,9 +47,9 @@ public: struct Parameters { walberla::id_t uid {UniqueID<data::Particle>::invalidID()}; walberla::mesa_pd::Vec3 position {real_t(0)}; + walberla::mesa_pd::Vec3 linearVelocity {real_t(0)}; walberla::mesa_pd::Rot3 rotation {}; walberla::mesa_pd::Vec3 angularVelocity {real_t(0)}; - walberla::mesa_pd::Vec3 linearVelocity {real_t(0)}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; walberla::real_t temperature {real_t(0)}; }; @@ -83,9 +83,9 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf.addDebugMarker( "un" ); buf << obj.particle_.getUid(); buf << obj.particle_.getPosition(); + buf << obj.particle_.getLinearVelocity(); buf << obj.particle_.getRotation(); buf << obj.particle_.getAngularVelocity(); - buf << obj.particle_.getLinearVelocity(); buf << obj.particle_.getOldContactHistory(); buf << obj.particle_.getTemperature(); return buf; @@ -97,9 +97,9 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf.readDebugMarker( "un" ); buf >> objparam.uid; buf >> objparam.position; + buf >> objparam.linearVelocity; buf >> objparam.rotation; buf >> objparam.angularVelocity; - buf >> objparam.linearVelocity; buf >> objparam.oldContactHistory; buf >> objparam.temperature; return buf; diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index efb734050..5cd319e21 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -173,6 +173,9 @@ waLBerla_execute_test( NAME MESA_PD_MPI_ReduceProperty PROCESSES 8 ) waLBerla_compile_test( NAME MESA_PD_MPI_ShapePackUnpack FILES mpi/ShapePackUnpack.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_MPI_ShapePackUnpack ) +waLBerla_compile_test( NAME MESA_PD_MPI_SyncNextNeighborsNoGhosts FILES mpi/SyncNextNeighborsNoGhosts.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_MPI_SyncNextNeighborsNoGhosts PROCESSES 2 ) + waLBerla_compile_test( NAME MESA_PD_MPI_VelocityCorrectionNotification FILES mpi/VelocityCorrectionNotification.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_MPI_VelocityCorrectionNotification PROCESSES 8) diff --git a/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp b/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp new file mode 100644 index 000000000..1dae83425 --- /dev/null +++ b/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp @@ -0,0 +1,90 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SyncNextNeighborsNoGhosts.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ParticleStorage.h> +#include <mesa_pd/domain/BlockForestDomain.h> +#include <mesa_pd/mpi/SyncNextNeighborsNoGhosts.h> + +#include <blockforest/Initialization.h> +#include <core/Environment.h> +#include <core/mpi/MPIManager.h> + +namespace walberla { +namespace mesa_pd { + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + walberla::mpi::MPIManager::instance()->useWorldComm(); + + //init domain partitioning + auto forest = blockforest::createBlockForest( math::AABB(0,0,0,10,10,10), // simulation domain + Vector3<uint_t>(2,1,1), // blocks in each direction + Vector3<bool>(false, false, false) // periodicity + ); + domain::BlockForestDomain domain(forest); + + data::ParticleStorage ps(100); + + Vec3 pt(2.5, 2.5, 2.5); + if (forest->begin()->getAABB().contains(pt)) + { + auto pIt = ps.create(); + pIt->setPosition(pt); + pIt->setInteractionRadius(real_t(0)); + pIt->setOwner(walberla::mpi::MPIManager::instance()->rank()); + } + + if (forest->begin()->getAABB().contains(pt)) + { + WALBERLA_CHECK_EQUAL(ps.size(), 1); + } else + { + WALBERLA_CHECK_EQUAL(ps.size(), 0); + } + + for (auto p : ps) + { + p.setPosition(Vec3(7.5, 2.5, 2.5)); + } + + mpi::SyncNextNeighborsNoGhosts SNN; + + SNN(ps, domain); + + if (forest->begin()->getAABB().contains(pt)) + { + WALBERLA_CHECK_EQUAL(ps.size(), 0); + } else + { + WALBERLA_CHECK_EQUAL(ps.size(), 1); + } + + return 0; +} + +} //namespace mesa_pd +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::mesa_pd::main(argc, argv); +} -- GitLab