diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..09f409f --- /dev/null +++ b/.clang-format @@ -0,0 +1,8 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +Standard: Cpp11 +AlwaysBreakTemplateDeclarations: true +PointerAlignment: Left +SpacesBeforeTrailingComments: 2 +... diff --git a/SConstruct b/SConstruct index 2f4e6d6..6813ce6 100644 --- a/SConstruct +++ b/SConstruct @@ -1,205 +1,298 @@ +# ------------------------------------------------------------------------------ +# Imports +# ------------------------------------------------------------------------------ from __future__ import print_function import os -from os.path import join, abspath +from os.path import join, abspath, basename from version import write_info_file - - +# ------------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------------ +# Helper functions +# ------------------------------------------------------------------------------ +def detect_fftw(env): + """Detect fftw on clusters""" + fftw_include = "" + fftw_library = "" + + # If FFTW is provided by module system (on clusters) + if 'FFTW_ROOT' in env['ENV']: + fftw_include = join(env['ENV']['FFTW_ROOT'], 'include') + fftw_library = join(env['ENV']['FFTW_ROOT'], 'lib') + + # Setting up FFTW + env['FFTW_LIBRARY_WISH'] = ['main', 'omp'] + env['FFTW_INCLUDE_DIR'] = fftw_include + env['FFTW_LIBRARY_DIR'] = fftw_library + env.Tool(fftw) + + +# ------------------------------------------------------------------------------ +def detect_cuda(env): + """Detect cuda on clusters""" + if 'CUDA_ROOT' in env['ENV']: + env['CUDA_TOOLKIT_PATH'] = env['ENV']['CUDA_ROOT'] + else: + env['CUDA_TOOLKIT_PATH'] = '/opt/cuda' + + env['CUDA_COMPONENTS'] = ['cufft'] + env['CUDA_ARCH_FLAG'] = '-arch=sm_35' + + colors = env['COLOR_DICT'] + if not env['verbose']: + env['NVCCCOMSTR'] = u'{0}[Compiling (cuda)] {1}$SOURCE{2}'.format(colors['green'], + colors['blue'], + colors['end']) + env['SHLINKCOMSTR'] = u'{0}[Linking (cuda)] {1}$TARGET{2}'.format(colors['purple'], + colors['blue'], + colors['end']) + env.AppendUnique(CXXFLAGS="-expt-extended-lambda") # experimental lambda support + env.AppendUnique(CXXFLAGS="-expt-relaxed-constexpr") # experimental lambda support + if env['build_type'] == 'debug': + env.AppendUnique(CXXFLAGS="-G") + env.Tool('nvcc') + + +# ------------------------------------------------------------------------------ +def detect_boost(env): + """Detect boost on clusters""" + if 'BOOST_ROOT' in env['ENV']: + env['BOOST_INCLUDE_DIR'] = join(env['ENV']['BOOST_ROOT'], 'include') + env.Tool(boost) + + +# ------------------------------------------------------------------------------ +def detect_thrust(env): + """Detect cuda on clusters""" + if 'CUDA_ROOT' in env['ENV']: + env['THRUST_INCLUDE_DIR'] = join(env['ENV']['CUDA_ROOT'], 'include') + else: + env['THRUST_INCLUDE_DIR'] = '/opt/cuda/include' + if basename(env['CXX']) == "clang++": + env.AppendUnique(CXXFLAGS=["-Wno-unused-local-typedef"]) + env.Tool(thrust) + + +# ------------------------------------------------------------------------------ def gen_print(action_string, color_string, env): """Generic function for creating pretty compile output""" if env['verbose']: return None def print_fun(command, target, source, env): colors = env['COLOR_DICT'] print("{}[{}] {}{}{}".format(colors[color_string], action_string, colors['blue'], target[0], colors['end'])) return print_fun +# ------------------------------------------------------------------------------ +# Main compilation +# ------------------------------------------------------------------------------ + # Compilation colors colors = { 'cyan': '\033[96m', 'purple': '\033[95m', 'blue': '\033[94m', 'green': '\033[92m', 'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' } # Inherit all environment variables (for CXX detection, etc.) main_env = Environment(ENV=os.environ) main_env['COLOR_DICT'] = colors # Compiler detection compiler_default = 'g++' if 'CXX' in os.environ: compiler_default = os.environ['CXX'] # Build variables vars = Variables('build-setup.conf') vars.Add(EnumVariable('build_type', 'Build type', 'release', allowed_values=('release', 'profiling', 'debug'), ignorecase=2)) +vars.Add(EnumVariable('backend', 'Thrust backend', 'omp', + allowed_values=('omp', 'cuda'), + ignorecase=2)) +vars.Add(EnumVariable('sanitizer', 'Sanitizer type', 'none', + allowed_values=('none', 'memory', 'leaks'), + ignorecase=2)) vars.Add('prefix', 'Prefix where to install', '/usr/local') vars.Add('CXX', 'Compiler', compiler_default) vars.Add('py_exec', 'Python executable', 'python') -vars.Add(BoolVariable('timer', 'Activate the timer possibilities', False)) vars.Add(BoolVariable('verbose', 'Activate verbosity', False)) vars.Add(BoolVariable('build_doc', 'Build documentation', False)) vars.Add(BoolVariable('color', 'Color the non-verbose compilation output', False)) vars.Update(main_env) Help(vars.GenerateHelpText(main_env)) # Save all options, not just those that differ from default with open('build-setup.conf', 'w') as setup: for key in vars.keys(): setup.write("{} = '{}'\n".format(key, main_env[key])) build_type = main_env['build_type'] build_dir = 'build-' + main_env['build_type'] print("Building in " + build_dir) verbose = main_env['verbose'] # Remove colors if not set if not main_env['color']: for key in colors: colors[key] = '' +# Setting object suffix +main_env['SHOBJSUFFIX'] = '.o' + if not verbose: - main_env['SHCXXCOMSTR'] = u'{0}[Compiling] {1}$SOURCE{2}'.format(colors['green'], - colors['blue'], - colors['end']) - main_env['SHLINKCOMSTR'] = u'{0}[Linking] {1}$TARGET{2}'.format(colors['purple'], - colors['blue'], - colors['end']) - main_env['SWIGCOMSTR'] = u'{0}[Swig] {1}$SOURCE{2}'.format(colors['yellow'], - colors['blue'], - colors['end']) + main_env['SHCXXCOMSTR'] = u'{0}[Compiling] {1}$SOURCE'.format(colors['green'], + colors['end']) + main_env['SHLINKCOMSTR'] = u'{0}[Linking] {1}$TARGET'.format(colors['purple'], + colors['end']) + main_env['SWIGCOMSTR'] = u'{0}[Swig] {1}$SOURCE'.format(colors['yellow'], + colors['end']) # Include paths main_env.AppendUnique(CPPPATH=['#/src', '#/src/core', '#/src/bem', '#/src/surface', '#/src/python', '#/src/percolation', '#/src/model', '#/src/solvers', + '#/src/gpu', '#/python']) # Changing the shared object extension main_env['SHOBJSUFFIX'] = '.o' -# Treating Intel compiler for OpenMP -if main_env['CXX'] != 'icpc': - omp_libs = ['gomp'] - omp_flag = '-fopenmp' -else: - omp_libs = [''] - omp_flag = '-qopenmp' +# Back to gcc if cuda is activated +if main_env['backend'] == "cuda": + main_env['CXX'] = "g++" + +# OpenMP flags - compiler dependent +omp_libs = { + "g++": ["gomp"], + "clang++": [], + "icpc": [] +} + +omp_flags = { + "g++": ["-fopenmp"], + "clang++": ["-fopenmp=libomp"], + "icpc": ["-qopenmp"] +} -main_env.AppendUnique(LIBS=omp_libs) -main_env.AppendUnique(LINKFLAGS=[omp_flag]) +omp_lib = omp_libs[main_env['CXX']] +omp_flag = omp_flags[main_env['CXX']] + +main_env.AppendUnique(LIBS=omp_lib) +main_env.AppendUnique(LINKFLAGS=omp_flag) # Flags and options -main_env.AppendUnique(CXXFLAGS=['-std=c++14', +main_env.AppendUnique(CXXFLAGS=['-std=c++11', '-Wall', omp_flag]) +if main_env['backend'] == 'omp': + main_env.AppendUnique(CPPDEFINES=["THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_OMP"]) +elif main_env['backend'] == 'cuda': + main_env.AppendUnique(CPPDEFINES=["THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CUDA"]) + main_env.AppendUnique(CPPDEFINES=['USE_CUDA']) + # Adding compile flags defined in evironment if 'CXXFLAGS' in os.environ: main_env.AppendUnique(CXXFLAGS=Split(os.environ['CXXFLAGS'])) -if main_env['timer']: - main_env.AppendUnique(CPPDEFINES=['USING_TIMER']) if build_type == 'debug': main_env.AppendUnique(CPPDEFINES=['TAMAAS_DEBUG']) +# Compilation flags cxxflags_dict = { - "debug": Split("-g -O0 -fsanitize=address -fno-omit-frame-pointer"), + "debug": Split("-g -O0"), "profiling": Split("-g -pg -O2 -fno-omit-frame-pointer"), "release": Split("-O3") } +# Link flags for shared libs shlinkflags_dict = { - "debug": Split("-fsanitize=address -fno-omit-frame-pointer"), + "debug": Split(""), "profiling": ['-pg'], "release": [] } +if main_env['sanitizer'] != 'none': + cxxflags_dict[build_type].append('-fsanitize={}'.format(main_env['sanitizer'])) + shlinkflags_dict[build_type].append('-fsanitize={}'.format(main_env['sanitizer'])) + main_env.AppendUnique(CXXFLAGS=cxxflags_dict[build_type]) main_env.AppendUnique(SHLINKFLAGS=shlinkflags_dict[build_type]) main_env.AppendUnique(LINKFLAGS=shlinkflags_dict[build_type]) main_env['LIBPATH'] = [abspath(join(build_dir, 'src'))] main_env['RPATH'] = "$LIBPATH" +detect_fftw(main_env) +detect_boost(main_env) +detect_thrust(main_env) -fftw_include = "" -fftw_library = "" - -# If FFTW is provided by module system (on clusters) -if 'FFTW_ROOT' in main_env['ENV']: - fftw_include = join(main_env['ENV']['FFTW_ROOT'], 'include') - fftw_library = join(main_env['ENV']['FFTW_ROOT'], 'lib') - -main_env = main_env.Clone( - tools=[fftw], - FFTW_LIBRARY_WISH=['main', 'omp'], - FFTW_INCLUDE_DIR=fftw_include, - FFTW_LIBRARY_DIR=fftw_library, -) - -# Find boost on clusters -if 'BOOST_ROOT' in main_env['ENV']: - main_env.AppendUnique(CPPPATH=[join(main_env['ENV']['BOOST_ROOT'], 'include')]) +# Activate cuda if needed +if main_env['backend'] == 'cuda': + detect_cuda(main_env) # Writing information file write_info_file("src/tamaas_info.cpp") # Saving the env file env_content = """export PYTHONPATH=$PYTHONPATH:{0}/python export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{0}/src """ def write_env_file(target, source, env): """Builder to write content to file""" with open(str(target[0]), 'w') as env_file: env_file.write(env_content.format(abspath(build_dir))) main_env['gen_print'] = gen_print env_file_env = main_env.Clone(PRINT_CMD_LINE_FUNC=gen_print("Writing", "cyan", main_env)) # Need to have a command and manage tamaas_environement.sh as target because # the build directory does not always exist env_file_env.Command(join(build_dir, 'tamaas_environement.sh'), None, write_env_file) - Export('main_env') # Building subdirs def subdir(dir): return SConscript(join(dir, 'SConscript'), variant_dir=join(build_dir, dir), duplicate=True) +subdirs2target = {'src': "tamaas", + 'python': "wrapper", + 'tests': "tests"} subdirs2target = {'src': "tamaas", 'python': "wrapper", 'tests': "tests"} for dir in subdirs2target: target = subdir(dir) main_env.Alias(subdirs2target[dir], target) # Building documentation if main_env['build_doc']: subdir('doc') diff --git a/examples/SConstruct b/examples/SConstruct index c871980..189b72a 100644 --- a/examples/SConstruct +++ b/examples/SConstruct @@ -1,12 +1,14 @@ import os env = Environment(CC = 'g++', CXXFLAGS = ['-std=c++11', '-g', '-fopenmp', '-O3'], TOOLS = ['default', tamaas], TAMAAS_PATH = '..', - TAMAAS_BUILD_TYPE = 'debug', + TAMAAS_BUILD_TYPE = 'release', LIBS = ['gomp', 'Tamaas'], ENV = os.environ) +env.AppendUnique(CPPPATH=['/opt/cuda/include']) +env.AppendUnique(LIBS=['fftw3', 'fftw3_omp']) env.Program('rough_surface.cc') diff --git a/examples/rough_surface.cc b/examples/rough_surface.cc index ac7aef6..6152e84 100644 --- a/examples/rough_surface.cc +++ b/examples/rough_surface.cc @@ -1,76 +1,91 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "tamaas.hh" -#include "bem_polonski.hh" -#include "surface_generator_filter_fft.hh" +#include "isopowerlaw.hh" +#include "surface_generator_filter.hh" +#include "polonsky_keer_rey.hh" +#include "model_factory.hh" /* -------------------------------------------------------------------------- */ using namespace tamaas; int main(int argc, char * argv[]) { /// Surface parameters UInt grid_size = 512; const UInt k0 = 4, k1 = 4, k2 = 32; const Real hurst = 0.8; const Real rms = 0.1; /// Initialize Tamaas initialize(); - /// Surface generation - SurfaceGeneratorFilterFFT sg; - sg.getGridSize() = grid_size; - sg.getQ0() = k0; - sg.getQ1() = k1; - sg.getQ2() = k2; - sg.getRMS() = rms; - sg.getHurst() = hurst; - sg.getRandomSeed() = 56; - sg.Init(); + /// Surface generation (2D) + SurfaceGeneratorFilter<2> sg; + sg.setSizes({grid_size, grid_size}); + sg.setRandomSeed(0); - Grid & grid = sg.buildSurface(); + Isopowerlaw<2> iso; + iso.setQ0(k0); + iso.setQ1(k1); + iso.setQ2(k2); + iso.setHurst(hurst); - /// Deprecated soon - Surface surface(grid_size, 1.); - surface.copy(grid); - std::cout << grid(0, 0, 0, 0) << std::endl; + sg.setFilter(&iso); - /// Bem initialization - BemPolonski bem(surface); - bem.setEffectiveModulus(1.); + std::cout << "Building rough surface with properties\n" + << " Q0 = " << k0 << '\n' + << " Q1 = " << k1 << '\n' + << " Q2 = " << k2 << '\n' + << " Hurst = " << hurst << '\n' + << " size = " << grid_size << "x" << grid_size << std::endl; + /// Making surface + GridBase & grid = sg.buildSurface(); + + std::cout << "Creating model" << std::endl; + + /// Model initialization + Model* model = ModelFactory::createModel(model_type::basic_2d, {1., 1.}, + {grid_size, grid_size}); Real load = 0.1; Real precision = 1e-12; + std::cout << "Solving contact problem" << std::endl; + /// Solve normal contact problem - bem.computeEquilibrium(precision, load); + PolonskyKeerRey solver{*model, grid, precision, PolonskyKeerRey::pressure, + PolonskyKeerRey::pressure}; + + solver.solve(load); + + std::cout << "Finished" << std::endl; /// Cleanup Tamaas finalize(); return EXIT_SUCCESS; } diff --git a/examples/site_scons/site_init.py b/examples/site_scons/site_init.py index 8346bcd..4df9ad8 100644 --- a/examples/site_scons/site_init.py +++ b/examples/site_scons/site_init.py @@ -1,37 +1,132 @@ from SCons.Script import * from os.path import * import os + +def fftw(env): + """A Tool to search for fftw headers and libraries""" + + if env.GetOption('clean'): + return + env.SetDefault(FFTW_VERSION='3') + env.SetDefault(FFTW_LIBRARY_WISH=[]) + + print("Building for fftw version {}".format(env['FFTW_VERSION'])) + + if 'FFTW_INCLUDE_DIR' in env: + env.AppendUnique(CPPPATH=env['FFTW_INCLUDE_DIR']) + + if 'FFTW_LIBRARY_DIR' in env: + env.AppendUnique(LIBPATH=env['FFTW_LIBRARY_DIR']) + + version = env['FFTW_VERSION'] + if version == "2": + lib_names = {'main': 'fftw'} + inc_names = ['fftw.h'] + else: + lib_names = {'main': 'fftw3', + 'thread': 'fftw3_threads', + 'omp': 'fftw3_omp'} + inc_names = ['fftw3.h'] + + try: + libs = [lib_names[i] for i in env['FFTW_LIBRARY_WISH']] + except: + raise SCons.Errors.StopError( + 'Incompatible wishlist {0} from version {1}'.format( + env['FFTW_LIBRARY_WISH'], env['FFTW_VERSION'])) + + env.AppendUnique(LIBS=libs) + if version == "2": + env.Append(LIBS='m') + + conf = Configure(env) + if not conf.CheckLibWithHeader(libs, inc_names, 'c++'): + raise SCons.Errors.StopError( + 'Failed to find libraries {0} or ' + 'headers {1}.'.format(str(lib_names), str(inc_names))) + + env = conf.Finish() + + +def criterion(env): + """A tool to configure for Criterion (test suite)""" + if env.GetOption('clean'): + return + + env.AppendUnique(CPPPATH=[Dir("#third-party/Criterion/include")], + LIBPATH=[abspath(str(Dir("#third-party/Criterion/build")))]) + conf = Configure(env) + # import pdb + # pdb.set_trace() + if not conf.CheckLibWithHeader('criterion', + 'criterion/criterion.h', + 'c++'): + raise SCons.Errors.StopError( + 'Failed to find library Criterion or criterion.h header in third-party') + env = conf.Finish() + + +def boost(env): + """A tool to confugure for boost""" + if env.GetOption('clean'): + return + + if 'BOOST_INCLUDE_DIR' in env: + env.AppendUnique(CPPPATH=env['BOOST_INCLUDE_DIR']) + conf = Configure(env) + if not conf.CheckCXXHeader('boost/version.hpp'): + raise SCons.Errors.StopError( + 'Failed to find Boost library') + env = conf.Finish() + + +def thrust(env): + """A tool to confugure for thrust""" + if env.GetOption('clean'): + return + + if 'THRUST_INCLUDE_DIR' in env: + env.AppendUnique(CPPPATH=env['THRUST_INCLUDE_DIR']) + conf = Configure(env) + if not conf.CheckCXXHeader('thrust/version.h'): + raise SCons.Errors.StopError( + 'Failed to find Thrust library') + env = conf.Finish() + + def tamaas(env): """Sets correct environement variables for Tamaas. - 'TAMAAS_PATH' is list of potential tamaas repositories - 'TAMAAS_BUILD_TYPE' is the build type of tamaas (release, debug, profiling)""" - if env.GetOption("clean"): return + if env.GetOption("clean"): + return try: - build_type = env['TAMAAS_BUILD_TYPE'] + build_type = env['TAMAAS_BUILD_TYPE'] except: - build_type = "release" + build_type = "release" if 'TAMAAS_PATH' not in env: - print "Please set the 'TAMAAS_PATH' variable in your scons environement" - Exit(1) + print("Please set the 'TAMAAS_PATH' variable in your scons environment") + Exit(1) tm_path = env['TAMAAS_PATH'] include_dir = tm_path + '/src' - subdirs = "core model bem surface".split(" ") + subdirs = "core model solvers gpu bem surface".split(" ") include_dirs = [abspath(join(include_dir, x)) for x in subdirs] lib_dir = join(tm_path, 'build-{}/src'.format(build_type)) env.AppendUnique(CPPPATH = include_dirs) + env.AppendUnique(CPPPATH = ['/opt/cuda/include']) # TODO fix this dirty hack env.AppendUnique(LIBPATH = [abspath(lib_dir)]) env.AppendUnique(RPATH = [abspath(lib_dir)]) - env.AppendUnique(CXXFLAGS = ["-std=c++11"]) + env.AppendUnique(CXXFLAGS = ["-std=c++14"]) conf = Configure(env) if not conf.CheckLibWithHeader("Tamaas", "tamaas.hh", language="CXX"): - raise SCons.Errors.StopError( - "Tamaas ({}) not found in {}".format(build_type, abspath(tm_path))) + raise SCons.Errors.StopError( + "Tamaas ({}) not found in {}".format(build_type, abspath(tm_path))) env['TAMAAS_PATH'] = abspath(tm_path) env = conf.Finish() diff --git a/python/SConscript b/python/SConscript index c43979a..7bd10db 100644 --- a/python/SConscript +++ b/python/SConscript @@ -1,60 +1,63 @@ from __future__ import print_function -from os.path import abspath +from os.path import abspath, basename from distutils.version import StrictVersion from subprocess import check_output, STDOUT Import('main_env') env_swig = main_env.Clone( tools=['swig'], SHLIBPREFIX='', ) if env_swig['SWIGVERSION'] is None: print("Could not find swig version") print(env_swig.Dictionary()) print(env_swig.Environment) Exit(1) if StrictVersion(env_swig['SWIGVERSION']) < StrictVersion("3.0"): print("Swig version {} is not supported by tamaas".format(env_swig['SWIGVERSION'])) Exit(1) # Check user's prefered version version_out = check_output([main_env['py_exec'], "--version"], stderr=STDOUT).split(' ') version = StrictVersion(version_out[-1]) python3 = version >= StrictVersion("3.0") print("Building wrapper for python version {}".format(version)) # Run code below to get versions from user preference and not scons versions_script = """ from __future__ import print_function import distutils.sysconfig as dsys from numpy.distutils.misc_util import get_numpy_include_dirs as numpy_dirs print(dsys.get_python_inc()) for d in numpy_dirs(): print(d)""" includes = check_output([main_env['py_exec'], "-c", versions_script]).split('\n') env_swig.AppendUnique(CPPPATH=includes) env_swig.AppendUnique(SWIGPATH=['$CPPPATH']) env_swig.AppendUnique(SWIGFLAGS=['-python', '-c++']) if python3: env_swig.AppendUnique(SWIGFLAGS=['-py3']) verbose = main_env['verbose'] if not verbose: env_swig.AppendUnique(SWIGFLAGS=['-w325', '-w315']) - env_swig.AppendUnique(CXXFLAGS=['-Wno-maybe-uninitialized']) # for some warning in wrapper code - +if basename(env_swig['CXX']) != "clang++": # for some warning in wrapper code + env_swig.AppendUnique(CXXFLAGS=['-Wno-maybe-uninitialized']) +else: + env_swig.AppendUnique(CXXFLAGS=['-Wno-uninitialized', + '-Wno-dynamic-class-memaccess']) env_swig.SharedLibrary( target='_tamaas.so', source=['tamaas.i'], LIBS=['Tamaas'], RPATH=[abspath('../src')] ) diff --git a/python/surface.i b/python/surface.i index 4e84d0a..f122106 100644 --- a/python/surface.i +++ b/python/surface.i @@ -1,343 +1,367 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ %{ #include #include #include "surface.hh" #include "types.hh" #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include #include "surface_generator_filter_fft.hh" #include "smart_pointer.hh" #include "surface_statistics.hh" -#include "surface_timer.hh" +#include "statistics.hh" #include "fftransform_fftw.hh" #include "flood_fill.hh" #include "model.hh" #include "model_factory.hh" #include "model_type.hh" #include "contact_solver.hh" #include "polonsky_keer_rey.hh" #include "bem_interface.hh" #include "bem_fft_base.hh" #include "bem_kato.hh" #include "bem_polonski.hh" #include "bem_gigi.hh" #include "bem_penalty.hh" #include "bem_uzawa.hh" #include "bem_gigipol.hh" #include "bem_grid.hh" #include "bem_grid_kato.hh" #include "bem_grid_polonski.hh" #include "bem_grid_teboulle.hh" #include "bem_grid_condat.hh" #include "bem_functional.hh" #include "bem_meta_functional.hh" #include "elastic_energy_functional.hh" #include "complimentary_term_functional.hh" #include "exponential_adhesion_functional.hh" #include "squared_exponential_adhesion_functional.hh" #include "maugis_adhesion_functional.hh" %} %include "cpointer.i" %include "typemaps.i" %include "numpy.i" %init %{ import_array(); %} /* -------------------------------------------------------------------------- */ /* Wrapping returned pointers /* -------------------------------------------------------------------------- */ //%include "typemaps.i" %include "std_string.i" %include "std_vector.i" %include "smart_pointer.hh" %template(VectorReal) std::vector; %template(VectorUInt) std::vector; //%pointer_functions(int, intp); //%pointer_functions(long, longp); //%pointer_functions(unsigned int, uintp); //%pointer_functions(double, doublep); //%pointer_functions(float, floatp); //%pointer_functions(std::complex, comlpexp); %define %my_pointer_class(NAME,TYPE) %template(SmartPointer##NAME) SmartPointer< TYPE >; %typemap(out) TYPE & { #define TOREPLACE SWIGTYPE_p_SmartPointerT_##NAME##_t SmartPointer * ptr = new SmartPointer($1); $result = SWIG_NewPointerObj(SWIG_as_voidptr(ptr), TOREPLACE, 0 | 0 ); #undef TOREPLACE } %enddef %my_pointer_class(int,int) %my_pointer_class(double,double) %my_pointer_class(long,long) %my_pointer_class(unsigned_int,tamaas::UInt) %my_pointer_class(vectorReal,std::vector) %my_pointer_class(vectorUInt,std::vector) %apply (unsigned int IN_ARRAY1[ANY]) {(tamaas::UInt n[ANY])}; /* -------------------------------------------------------------------------- */ /* Wrapping Surface class */ /* -------------------------------------------------------------------------- */ %include "tamaas.hh" %ignore *::operator=; %ignore *::operator++; %ignore *::begin; %ignore *::end; %ignore GridBase; %ignore Grid; %ignore GridHermitian; %ignore Surface; %ignore SurfaceComplex; %ignore GridBase::iterator; %include "grid_base.hh" %include "grid.hh" %include "grid_hermitian.hh" %include "types.hh" %include "surface.hh" %include "surface_complex.hh" %inline %{ __BEGIN_TAMAAS__ template void sanityCheck(PyObject * input) { if (PyArray_TYPE((PyArrayObject*)input) != required_type) throw Exception("Sanity check: python object stores wrong type"); } __END_TAMAAS__ %} %{ #include "python/grid_python.hh" #include "python/surface_python.hh" %} %define %grid_typemaps(GRID_CLASS, DATA_TYPE, DATA_TYPECODE, DIM) +// Typemap for returned references %typemap(out, fragment="NumPy_Fragments") (GRID_CLASS &) { using namespace tamaas; UInt additional_dim = ($1->getNbComponents() == 1)? 0:1; UInt dim = DIM+additional_dim; npy_intp dims[dim]; for (UInt i = 0 ; i < DIM ; i++) dims[i] = (npy_intp)$1->sizes()[i]; if (additional_dim) dims[dim-1] = $1->getNbComponents(); GRID_CLASS::value_type * data = const_cast::value_type *>($1->getInternalData()); PyObject* obj = PyArray_SimpleNewFromData(dim, dims, DATA_TYPECODE, &data[0]); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result, obj); } +// Typemap for returned objects as values +%typemap(out, fragment="NumPy_Fragments") (GRID_CLASS) +{ + using namespace tamaas; + auto * one = new GRID_CLASS($1); // We have to copy :( + UInt additional_dim = (one->getNbComponents() == 1)? 0:1; + UInt dim = DIM+additional_dim; + npy_intp dims[dim]; + for (UInt i = 0 ; i < DIM ; i++) dims[i] = (npy_intp)one->sizes()[i]; + if (additional_dim) + dims[dim-1] = one->getNbComponents(); + + GRID_CLASS::value_type * data + = const_cast::value_type *>(one->getInternalData()); + PyObject* obj = PyArray_SimpleNewFromData(dim, + dims, + DATA_TYPECODE, + &data[0]); + PyArrayObject* array = (PyArrayObject*) obj; + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result, obj); +} + %typemap(in) GRID_CLASS & { using namespace tamaas; if (!PyArray_Check($input)) { PyObject* objectsRepresentation = PyObject_Repr(PyObject_Type($input)); const char* s = PyString_AsString(objectsRepresentation); std::string __type = s; // Remove namespace (tamaas::) from class name std::string basename = std::string("GRID_CLASS").substr(8); std::set types = { "", "" }; if (types.find(__type) != types.end()) { SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0); } else throw tamaas::Exception("typemap: incompatible input which is not a proper type: " + __type + " (DATATYPE = " + std::string("DATA_TYPE") + ")"); } else { $1 = new tamaas::GridPython< GRID_CLASS >($input); sanityCheck< DATA_TYPECODE >($input); } } %inline %{ namespace tamaas { GRID_CLASS & convertGrid(GRID_CLASS & s){ return s; } } + %} %enddef %define %surface_typemaps(SURFACE_CLASS, DATA_TYPE, DATA_TYPECODE) %typemap(out, fragment="NumPy_Fragments") (SURFACE_CLASS &) { using namespace tamaas; UInt nz = $1->size(); npy_intp dims[2] = {nz,nz}; DATA_TYPE * data = const_cast($1->getInternalData()); PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, &data[0]); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result, obj); } %typemap(in) tamaas::Surface< DATA_TYPE > & { using namespace tamaas; if (!PyArray_Check($input)){ PyObject* objectsRepresentation = PyObject_Repr(PyObject_Type($input)); const char* s = PyString_AsString(objectsRepresentation); std::string __type = s; if ("" == __type) { SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0); } else if ("" == __type) { SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0); } else if ("" == __type) { SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0); } else throw tamaas::Exception("typemap: incompatible input which is not a proper type: " + __type + " (DATATYPE = " + std::string("DATA_TYPE") + ")"); } else{ $1 = new SurfaceForPython< DATA_TYPE >($input); sanityCheck< DATA_TYPECODE >($input); } } %inline %{ namespace tamaas { SURFACE_CLASS & convertSurface(SURFACE_CLASS & s){ return s; } } %} %enddef %surface_typemaps(tamaas::Surface, Real, NPY_DOUBLE) -%surface_typemaps(tamaas::SurfaceComplex, std::complex, NPY_COMPLEX128 ) +%surface_typemaps(tamaas::SurfaceComplex, tamaas::complex, NPY_COMPLEX128 ) %surface_typemaps(tamaas::Surface, unsigned long, NPY_UINT ) %surface_typemaps(tamaas::Surface, UInt, NPY_UINT ) %surface_typemaps(tamaas::Surface, int, NPY_INT ) // Must use c-type names here for some reason %grid_typemaps(tamaas::Grid, double, NPY_DOUBLE, 1) %grid_typemaps(tamaas::Grid, double, NPY_DOUBLE, 2) %grid_typemaps(tamaas::Grid, bool, NPY_BOOL, 2) %grid_typemaps(tamaas::GridHermitian, double, NPY_COMPLEX128, 2) %grid_typemaps(tamaas::Grid, unsigned int, NPY_UINT, 2) // Typemaps for GridBase output %define GRID_BASE_MACRO(GRID_CLASS, DATA_TYPE, DATA_TYPECODE, DIM) if (GRID_CLASS * grid = dynamic_cast($1)) { UInt additional_dim = ($1->getNbComponents() == 1)? 0:1; UInt dim = DIM+additional_dim; npy_intp dims[dim]; for (UInt i = 0 ; i < DIM ; i++) dims[i] = (npy_intp)grid->sizes()[i]; if (additional_dim) dims[dim-1] = $1->getNbComponents(); GRID_CLASS::value_type * data = const_cast::value_type *>(grid->getInternalData()); PyObject* obj = PyArray_SimpleNewFromData(dim, dims, DATA_TYPECODE, &data[0]); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result, obj); } %enddef %define %gridbase_typemaps(GRID_CLASS, DATA_TYPE, DATA_TYPECODE) %typemap(out, fragment="NumPy_Fragments") (tamaas::GridBase &) { using namespace tamaas; GRID_BASE_MACRO(GRID_CLASS, DATA_TYPE, DATA_TYPECODE, 1); GRID_BASE_MACRO(GRID_CLASS, DATA_TYPE, DATA_TYPECODE, 2); GRID_BASE_MACRO(GRID_CLASS, DATA_TYPE, DATA_TYPECODE, 3); } %typemap(in) tamaas::GridBase & { using namespace tamaas; if (!PyArray_Check($input)) { PyObject* objectsRepresentation = PyObject_Repr(PyObject_Type($input)); const char* s = PyString_AsString(objectsRepresentation); std::string __type = s; // Remove namespace (tamaas::) from class name std::string basename = std::string("GRID_CLASS").substr(8); std::set types = { "", "" }; if (types.find(__type) != types.end()) { SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0); } else throw tamaas::Exception("typemap: incompatible input which is not a proper type: " + __type + " (DATATYPE = " + std::string("DATA_TYPE") + ")"); } else { int _n = PyArray_NDIM((PyArrayObject*)$input); switch(_n) { case 1: $1 = new tamaas::GridPython< GRID_CLASS >($input); break; case 2: $1 = new tamaas::GridPython< GRID_CLASS >($input); break; default: throw tamaas::Exception("typemap (GridBase): dimensions higher than 2 not supported. This typemap is designed for surfaces"); } sanityCheck< DATA_TYPECODE >($input); } } %enddef %gridbase_typemaps(tamaas::Grid, double, NPY_DOUBLE); -%include "surface_timer.hh" diff --git a/python/surface_statistics.i b/python/surface_statistics.i index 89b3dfa..71ce7f9 100644 --- a/python/surface_statistics.i +++ b/python/surface_statistics.i @@ -1,38 +1,42 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* Wrapping surface statistics /* -------------------------------------------------------------------------- */ //%include "surface.i" %include "surface_statistics.hh" %template(computeDistribution) tamaas::SurfaceStatistics::computeDistribution; %template(computeDistributionWithZeros) tamaas::SurfaceStatistics::computeDistribution; %template(vecInt) std::vector; //%include "contact_area.hh" //%include "contact_cluster_collection.hh" +%include "statistics.hh" +%template(Statistics1D) tamaas::Statistics<1>; +%template(Statistics2D) tamaas::Statistics<2>; + diff --git a/python/tamaas.i b/python/tamaas.i index 3866fc4..a8f3be6 100644 --- a/python/tamaas.i +++ b/python/tamaas.i @@ -1,50 +1,55 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ %module tamaas %include std_except.i +%include std_map.i +%include std_string.i + //%exception { // try { // $action // } // catch (tamaas::Exception e) { // PyErr_SetString(PyExc_IndexError,e.what()); // return NULL; // } // } %{ #include "tamaas.hh" %} +/* %template(MapStringReal) std::map; */ + %include "tamaas.hh" %include "surface.i" %include "surface_generator.i" %include "surface_statistics.i" %include "bem.i" %include "clusters.i" diff --git a/site_scons/site_init.py b/site_scons/site_init.py index a36f29a..855b99e 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -1,101 +1,131 @@ from SCons.Script import * from os.path import * import os def fftw(env): """A Tool to search for fftw headers and libraries""" if env.GetOption('clean'): return env.SetDefault(FFTW_VERSION='3') env.SetDefault(FFTW_LIBRARY_WISH=[]) print("Building for fftw version {}".format(env['FFTW_VERSION'])) if 'FFTW_INCLUDE_DIR' in env: env.AppendUnique(CPPPATH=env['FFTW_INCLUDE_DIR']) if 'FFTW_LIBRARY_DIR' in env: env.AppendUnique(LIBPATH=env['FFTW_LIBRARY_DIR']) version = env['FFTW_VERSION'] if version == "2": lib_names = {'main': 'fftw'} inc_names = ['fftw.h'] else: lib_names = {'main': 'fftw3', 'thread': 'fftw3_threads', 'omp': 'fftw3_omp'} inc_names = ['fftw3.h'] try: libs = [lib_names[i] for i in env['FFTW_LIBRARY_WISH']] except: raise SCons.Errors.StopError( 'Incompatible wishlist {0} from version {1}'.format( env['FFTW_LIBRARY_WISH'], env['FFTW_VERSION'])) env.AppendUnique(LIBS=libs) if version == "2": env.Append(LIBS='m') conf = Configure(env) if not conf.CheckLibWithHeader(libs, inc_names, 'c++'): raise SCons.Errors.StopError( 'Failed to find libraries {0} or ' 'headers {1}.'.format(str(lib_names), str(inc_names))) env = conf.Finish() def criterion(env): """A tool to configure for Criterion (test suite)""" if env.GetOption('clean'): return env.AppendUnique(CPPPATH=[Dir("#third-party/Criterion/include")], LIBPATH=[abspath(str(Dir("#third-party/Criterion/build")))]) conf = Configure(env) + # import pdb + # pdb.set_trace() if not conf.CheckLibWithHeader('criterion', 'criterion/criterion.h', 'c++'): raise SCons.Errors.StopError( 'Failed to find library Criterion or criterion.h header in third-party') env = conf.Finish() +def boost(env): + """A tool to confugure for boost""" + if env.GetOption('clean'): + return + + if 'BOOST_INCLUDE_DIR' in env: + env.AppendUnique(CPPPATH=env['BOOST_INCLUDE_DIR']) + conf = Configure(env) + if not conf.CheckCXXHeader('boost/version.hpp'): + raise SCons.Errors.StopError( + 'Failed to find Boost library') + env = conf.Finish() + + +def thrust(env): + """A tool to confugure for thrust""" + if env.GetOption('clean'): + return + + if 'THRUST_INCLUDE_DIR' in env: + env.AppendUnique(CPPPATH=env['THRUST_INCLUDE_DIR']) + conf = Configure(env) + if not conf.CheckCXXHeader('thrust/version.h'): + raise SCons.Errors.StopError( + 'Failed to find Thrust library') + env = conf.Finish() + + def tamaas(env): """Sets correct environement variables for Tamaas. - 'TAMAAS_PATH' is list of potential tamaas repositories - 'TAMAAS_BUILD_TYPE' is the build type of tamaas (release, debug, profiling)""" if env.GetOption("clean"): return try: build_type = env['TAMAAS_BUILD_TYPE'] except: build_type = "release" if 'TAMAAS_PATH' not in env: print("Please set the 'TAMAAS_PATH' variable in your scons environment") Exit(1) tm_path = env['TAMAAS_PATH'] include_dir = tm_path + '/src' subdirs = "core model bem surface".split(" ") include_dirs = [abspath(join(include_dir, x)) for x in subdirs] lib_dir = join(tm_path, 'build-{}/src'.format(build_type)) env.AppendUnique(CPPPATH = include_dirs) env.AppendUnique(LIBPATH = [abspath(lib_dir)]) env.AppendUnique(RPATH = [abspath(lib_dir)]) env.AppendUnique(CXXFLAGS = ["-std=c++14"]) conf = Configure(env) if not conf.CheckLibWithHeader("Tamaas", "tamaas.hh", language="CXX"): raise SCons.Errors.StopError( "Tamaas ({}) not found in {}".format(build_type, abspath(tm_path))) env['TAMAAS_PATH'] = abspath(tm_path) env = conf.Finish() diff --git a/site_scons/site_tools/nvcc.py b/site_scons/site_tools/nvcc.py new file mode 100644 index 0000000..d4db9e4 --- /dev/null +++ b/site_scons/site_tools/nvcc.py @@ -0,0 +1,203 @@ +# coding: utf-8 +# +# @author Lucas Frérot +# +# Based on version +# https://github.com/thrust/thrust/blob/master/site_scons/site_tools/nvcc.py +# +# @section LICENSE +# +# Copyright (©) 2017 EPFL (Ecole Polytechnique Fédérale de +# Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des +# Solides) +# +# Tamaas is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Tamaas. If not, see . + +from __future__ import print_function + +import SCons +from SCons.Errors import StopError + +import platform +from os.path import join + +known_components = { + 'cufft': 'cufft.h', + 'cufftw': 'cufftw.h' +} + + +def _find_cuda_paths(env): + """Finding cuda paths""" + if 'CUDA_TOOLKIT_PATH' not in env: + raise StopError("CUDA_TOOLKIT_PATH variable not found in environment") + + cuda_path = env['CUDA_TOOLKIT_PATH'] + inc_path = join(cuda_path, 'include') + lib_path = join(cuda_path, 'lib') + bin_path = join(cuda_path, 'bin') + if platform.machine()[-2:] == '64': + lib_path += '64' + + # add nvcc's location to PATH + env.PrependENVPath('PATH', bin_path) + + # add the location of the cudart shared library to LD_LIBRARY_PATH as well + # this allows us to execute CUDA programs during the build + env.PrependENVPath('LD_LIBRARY_PATH', lib_path) + + # add to include paths + env.AppendUnique(CPPPATH=[inc_path]) + # add to library paths + env.AppendUnique(LIBPATH=[lib_path]) + + +def _configure_cuda_components(env): + """Finding required components in cuda""" + if env.GetOption('clean'): + return + if 'CUDA_COMPONENTS' in env: + for component in env['CUDA_COMPONENTS']: + if component not in known_components: + raise StopError("Unknown cuda component '{}'".format(component)) + conf = SCons.Script.Configure(env) + if not conf.CheckLibWithHeader(component, known_components[component], 'c++'): + raise StopError("Failed to find library {} or header {}".format( + component, known_components[component])) + env = conf.Finish() + + +def _define_compile_cuda(env): + """Define the compile string for files that need nvcc""" + env['NVCC'] = env.Detect('nvcc') + + # Setting compilation command + env['NVCCCOM'] = \ + '$NVCC $CUDA_ARCH_FLAG -o $TARGET -c $NVCC_CXXFLAGS $NVCC_CCFLAGS $_CCCOMCOM -x cu $SOURCES' + env['SHNVCCCOM'] = \ + '$NVCC $CUDA_ARCH_FLAG -o $TARGET -dc -Xcompiler -fPIC $NVCC_CXXFLAGS $NVCC_CCFLAGS $_CCCOMCOM -x cu $SOURCES' + + # Constructing proper cc flags + env['_NVCC_BARE_CCFLAGS'] = \ + '${_concat("", CCFLAGS, "", __env__, _NVCC_BARE_FILTER)}' + env['_NVCC_PASSED_CCFLAGS'] = \ + '${_concat("-Xcompiler ", CCFLAGS, "", __env__, _NVCC_COMPILER_PASSED_FILTER)}' + + # Constructing proper cxx flags + env['_NVCC_BARE_CXXFLAGS'] = \ + '${_concat("", CXXFLAGS, "", __env__, _NVCC_BARE_FILTER)}' + env['_NVCC_PASSED_CXXFLAGS'] = \ + '${_concat("-Xcompiler ", CXXFLAGS, "", __env__, _NVCC_COMPILER_PASSED_FILTER)}' + + # Putting all together + env['NVCC_CCFLAGS'] = '$_NVCC_BARE_CCFLAGS $_NVCC_PASSED_CCFLAGS' + env['NVCC_CXXFLAGS'] = '$_NVCC_BARE_CXXFLAGS $_NVCC_PASSED_CXXFLAGS' + + +def _define_link_cuda(env): + """Define the link string""" + # Fixing rpaths + env['RPATHPREFIX'] = '-rpath=' + env['__RPATH'] = '${_concat("-Xlinker ", _RPATH, "", __env__)}' + + env['LINK'] = env['NVCC'] + env['SHLINK'] = env['NVCC'] + + # Replacing old link command strings + env['LINKCOM'] = \ + '$LINK $CUDA_ARCH_FLAG -o $TARGET $NVCC_LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env['SHLINKCOM'] = \ + '$SHLINK -shared $CUDA_ARCH_FLAG -o $TARGET $NVCC_SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + + # Constructing proper static linker flags + env['_NVCC_BARE_LINKFLAGS'] = \ + '${_concat("", LINKFLAGS, "", __env__, _NVCC_BARE_FILTER)}' + env['_NVCC_COMPILER_LINKFLAGS'] = \ + '${_concat("-Xcompiler ", LINKFLAGS, "", __env__, _NVCC_COMPILER_FILTER)}' + env['_NVCC_PASSED_LINKFLAGS'] = \ + '${_concat("-Xlinker ", LINKFLAGS, "", __env__, _NVCC_LINK_PASSED_FILTER)}' + # Constructing proper shared linker flags + env['_NVCC_BARE_SHLINKFLAGS'] = \ + '${_concat("", SHLINKFLAGS, "", __env__, _NVCC_BARE_FILTER)}' + env['_NVCC_COMPILER_SHLINKFLAGS'] = \ + '${_concat("-Xcompiler ", LINKFLAGS, "", __env__, _NVCC_COMPILER_FILTER)}' + env['_NVCC_PASSED_SHLINKFLAGS'] = \ + '${_concat("-Xlinker ", SHLINKFLAGS, "", __env__, _NVCC_LINK_PASSED_FILTER)}' + + # Putting all together + env['NVCC_LINKFLAGS'] = \ + '$_NVCC_BARE_LINKFLAGS $_NVCC_COMPILER_LINKFLAGS $_NVCC_PASSED_LINKFLAGS' + env['NVCC_SHLINKFLAGS'] = env['NVCC_LINKFLAGS'] + env['NVCC_SHLINKFLAGS'] += \ + ' $_NVCC_BARE_SHLINKFLAGS $_NVCC_COMPILER_SHLINKFLAGS $_NVCC_PASSED_SHLINKFLAGS' + + +def _define_commands(env): + """Defining the command strings""" + + # Flags allowed by nvcc + bare_flags = """-std=c++11 -O0 -O1 -O2 -O3 -g -pg -G -w""".split() + # Experimental flags + bare_flags += """-expt-extended-lambda -expt-relaxed-constexpr""".split() + + # Flags that must be passed to compiler at link time + compiler_flags = """-fopenmp -qopenmp""".split() + + # Pass flags bare to nvcc + env['_NVCC_BARE_FILTER'] = lambda flags: list(filter(lambda flag: flag in bare_flags, flags)) + # Must prepend -Xcompiler, even at link time + env['_NVCC_COMPILER_FILTER'] = lambda flags: list(filter( + lambda flag: flag in compiler_flags, flags)) + # Prepend -Xcompiler + env['_NVCC_COMPILER_PASSED_FILTER'] = lambda flags: list(filter( + lambda flag: flag not in set(bare_flags), flags)) + # Prepend -Xlinker + env['_NVCC_LINKED_PASSED_FILTER'] = lambda flags: list(filter( + lambda flag: flag not in set(bare_flags) | set(compiler_flags), flags)) + + _define_compile_cuda(env) + _define_link_cuda(env) + + +def _add_actions_cuda(env): + """Adding actions to .cu files to compile with nvcc. Other files are not affected.""" + nvcc_action = SCons.Action.Action('$NVCCCOM', '$NVCCCOMSTR') + shnvcc_action = SCons.Action.Action('$SHNVCCCOM', '$NVCCCOMSTR') + + static, shared = SCons.Tool.createObjBuilders(env) + + # Compiling with nvcc action added to detected .cu files + static.add_action('.cu', nvcc_action) + shared.add_action('.cu', shnvcc_action) + # Emitter to qualify correctly object code type + static.add_emitter('.cu', SCons.Defaults.StaticObjectEmitter) + shared.add_emitter('.cu', SCons.Defaults.SharedObjectEmitter) + + env['CXXCOM'] = '$NVCCCOM' + env['SHCXXCOM'] = '$SHNVCCCOM' + + # Scanner for dependency calculations + SCons.Tool.SourceFileScanner.add_scanner('.cu', SCons.Scanner.C.CScanner()) + + +def generate(env): + """Setup environment for compiling .cu files with nvcc""" + _find_cuda_paths(env) + _add_actions_cuda(env) + _define_commands(env) + _configure_cuda_components(env) + + +def exists(env): + return env.Detect('nvcc') diff --git a/site_scons/site_tools/swig.py b/site_scons/site_tools/swig.py index 74c5a8e..887f94f 100644 --- a/site_scons/site_tools/swig.py +++ b/site_scons/site_tools/swig.py @@ -1,193 +1,202 @@ """SCons.Tool.swig Tool-specific initialization for swig. There normally shouldn't be any need to import this module directly. It will usually be imported through the generic SCons.Tool.Tool() selection method. """ # # Copyright (c) 2001 - 2015 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # __revision__ = "src/engine/SCons/Tool/swig.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog" import os.path import re import subprocess import SCons.Action import SCons.Defaults import SCons.Scanner import SCons.Tool import SCons.Util import SCons.Node -swigs = [ 'swig', 'swig3.0', 'swig2.0' ] +swigs = ['swig', 'swig3.0', 'swig2.0'] SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR') + def swigSuffixEmitter(env, source): if '-c++' in SCons.Util.CLVar(env.subst("$SWIGFLAGS", source=source)): return '$SWIGCXXFILESUFFIX' else: return '$SWIGCFILESUFFIX' + # Match '%module test', as well as '%module(directors="1") test' # Also allow for test to be quoted (SWIG permits double quotes, but not single) # Also allow for the line to have spaces after test if not quoted _reModule = re.compile(r'%module(\s*\(.*\))?\s+("?)(\S+)\2') + def _find_modules(src): """Find all modules referenced by %module lines in `src`, a SWIG .i file. Returns a list of all modules, and a flag set if SWIG directors have been requested (SWIG will generate an additional header file in this case.)""" directors = 0 mnames = [] try: matches = _reModule.findall(open(src).read()) except IOError: # If the file's not yet generated, guess the module name from the file stem matches = [] mnames.append(os.path.splitext(os.path.basename(src))[0]) for m in matches: mnames.append(m[2]) directors = directors or m[0].find('directors') >= 0 return mnames, directors + def _add_director_header_targets(target, env): # Directors only work with C++ code, not C suffix = env.subst(env['SWIGCXXFILESUFFIX']) # For each file ending in SWIGCXXFILESUFFIX, add a new target director # header by replacing the ending with SWIGDIRECTORSUFFIX. for x in target[:]: n = x.name d = x.dir if n[-len(suffix):] == suffix: target.append(d.File(n[:-len(suffix)] + env['SWIGDIRECTORSUFFIX'])) + def _swigEmitter(target, source, env): swigflags = env.subst("$SWIGFLAGS", target=target, source=source) flags = SCons.Util.CLVar(swigflags) for src in source: src = str(src.rfile()) mnames = None if "-python" in flags and "-noproxy" not in flags: if mnames is None: mnames, directors = _find_modules(src) if directors: _add_director_header_targets(target, env) python_files = [m + ".py" for m in mnames] outdir = env.subst('$SWIGOUTDIR', target=target, source=source) # .py files should be generated in SWIGOUTDIR if specified, # otherwise in the same directory as the target if outdir: python_files = [env.fs.File(os.path.join(outdir, j)) for j in python_files] else: python_files = [target[0].dir.File(m) for m in python_files] target.extend(python_files) if "-java" in flags: if mnames is None: mnames, directors = _find_modules(src) if directors: _add_director_header_targets(target, env) java_files = [[m + ".java", m + "JNI.java"] for m in mnames] java_files = SCons.Util.flatten(java_files) outdir = env.subst('$SWIGOUTDIR', target=target, source=source) if outdir: - java_files = [os.path.join(outdir, j) for j in java_files] + java_files = [os.path.join(outdir, j) for j in java_files] java_files = list(map(env.fs.File, java_files)) + def t_from_s(t, p, s, x): return t.dir tsm = SCons.Node._target_from_source_map tkey = len(tsm) tsm[tkey] = t_from_s for jf in java_files: jf._func_target_from_source = tkey target.extend(java_files) return (target, source) + def _get_swig_version(env, swig): """Run the SWIG command line tool to get and return the version number""" swig = env.subst(swig) pipe = SCons.Action._subproc(env, SCons.Util.CLVar(swig) + ['-version'], - stdin = 'devnull', - stderr = 'devnull', - stdout = subprocess.PIPE) + stdin='devnull', + stderr='devnull', + stdout=subprocess.PIPE) if pipe.wait() != 0: return out = pipe.stdout.read() match = re.search(r'SWIG Version\s+(\S+)$', out, re.MULTILINE) if match: return match.group(1) + def generate(env): """Add Builders and construction variables for swig to an Environment.""" c_file, cxx_file = SCons.Tool.createCFileBuilders(env) c_file.suffix['.i'] = swigSuffixEmitter cxx_file.suffix['.i'] = swigSuffixEmitter c_file.add_action('.i', SwigAction) c_file.add_emitter('.i', _swigEmitter) cxx_file.add_action('.i', SwigAction) cxx_file.add_emitter('.i', _swigEmitter) java_file = SCons.Tool.CreateJavaFileBuilder(env) java_file.suffix['.i'] = swigSuffixEmitter java_file.add_action('.i', SwigAction) java_file.add_emitter('.i', _swigEmitter) if 'SWIG' not in env: env['SWIG'] = env.Detect(swigs) or swigs[0] env['SWIGVERSION'] = _get_swig_version(env, env['SWIG']) env['SWIGFLAGS'] = SCons.Util.CLVar('') env['SWIGDIRECTORSUFFIX'] = '_wrap.h' env['SWIGCFILESUFFIX'] = '_wrap$CFILESUFFIX' env['SWIGCXXFILESUFFIX'] = '_wrap$CXXFILESUFFIX' env['_SWIGOUTDIR'] = r'${"-outdir \"%s\"" % SWIGOUTDIR}' env['SWIGPATH'] = [] env['SWIGINCPREFIX'] = '-I' env['SWIGINCSUFFIX'] = '' env['_SWIGINCFLAGS'] = '$( ${_concat(SWIGINCPREFIX, SWIGPATH, SWIGINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' env['SWIGCOM'] = '$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS} $SWIGFLAGS $SOURCES' expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' scanner = SCons.Scanner.ClassicCPP("SWIGScan", ".i", "SWIGPATH", expr) - env.Append(SCANNERS = scanner) + env.Append(SCANNERS=scanner) + def exists(env): - swig = env.get('SWIG') or env.Detect(['swig']) + swig = env.get('SWIG') or env.Detect(swigs) return swig # Local Variables: # tab-width:4 # indent-tabs-mode:nil # End: # vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/SConscript b/src/SConscript index 21c40c3..ac67a0e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,97 +1,108 @@ import os Import('main_env') def prepend(path, list): return [os.path.join(path, x) for x in list] env = main_env # Core core_list = """ fft_plan_manager.cpp fftransform.cpp fftransform_fftw.cpp grid.cpp grid_hermitian.cpp +statistics.cpp surface.cpp -surface_timer.cpp tamaas.cpp types.cpp +loop.cpp """.split() core_list = prepend('core', core_list) core_list.append('tamaas_info.cpp') # Lib roughcontact generator_list = """ surface_generator.cpp surface_generator_filter.cpp surface_generator_filter_fft.cpp isopowerlaw.cpp """.split() generator_list = prepend('surface', generator_list) # Lib PERCOLATION percolation_list = """ flood_fill.cpp """.split() percolation_list = prepend('percolation', percolation_list) # BEM PERCOLATION bem_list = """ bem_kato.cpp bem_polonski.cpp bem_gigi.cpp bem_gigipol.cpp bem_penalty.cpp bem_uzawa.cpp bem_fft_base.cpp bem_functional.cpp bem_meta_functional.cpp elastic_energy_functional.cpp exponential_adhesion_functional.cpp squared_exponential_adhesion_functional.cpp maugis_adhesion_functional.cpp complimentary_term_functional.cpp bem_grid.cpp bem_grid_polonski.cpp bem_grid_kato.cpp bem_grid_teboulle.cpp bem_grid_condat.cpp """.split() bem_list = prepend('bem', bem_list) # Model model_list = """ model.cpp model_factory.cpp model_type.cpp model_template.cpp westergaard.cpp elastic_functional.cpp meta_functional.cpp """.split() model_list = prepend('model', model_list) # Solvers solvers_list = """ contact_solver.cpp polonsky_keer_rey.cpp """.split() solvers_list = prepend('solvers', solvers_list) +# GPU API +gpu_list = """ +fftransform_cufft.cpp +""".split() +gpu_list = prepend('gpu', gpu_list) + # Assembling total list rough_contact_list = \ core_list + generator_list + percolation_list + model_list + solvers_list + bem_list +# Adding GPU if needed +if env['backend'] == 'cuda': + rough_contact_list += gpu_list + # Generating dependency files # env.AppendUnique(CXXFLAGS=['-MMD']) # for file_name in rough_contact_list: # obj = file_name.replace('.cpp', '.os') # dep_file_name = file_name.replace('.cpp', '.d') # env.SideEffect(dep_file_name, obj) # env.ParseDepends(dep_file_name) -env.SharedLibrary('Tamaas', rough_contact_list) +libTamaas = env.SharedLibrary('Tamaas', rough_contact_list) diff --git a/src/bem/bem_fft_base.cpp b/src/bem/bem_fft_base.cpp index 16657e7..8de76d4 100644 --- a/src/bem/bem_fft_base.cpp +++ b/src/bem/bem_fft_base.cpp @@ -1,240 +1,199 @@ /** + * @file * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" -#include "surface_statistics.hh" #include "bem_meta_functional.hh" #include "elastic_energy_functional.hh" #include "fft_plan_manager.hh" +#include "surface_statistics.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -BemFFTBase::BemFFTBase(Surface & p): - BemInterface(p), - functional(new MetaFunctional(*this)), - surface_tractions(p.size(),p.getL()), - surface_displacements(p.size(),p.getL()), - surface_spectral_input(p.size(),p.getL()), - surface_spectral_output(p.size(),p.getL()), - surface_spectral_influence_disp(p.size(),p.getL()), - true_displacements(p.size(),p.getL()), - old_displacements(p.size(),p.getL()), - gap(p.size(),p.getL()), - e_star(std::nan("")), - tmp_coeff(1./M_PI){ +BemFFTBase::BemFFTBase(Surface& p) + : BemInterface(p), functional(new MetaFunctional(*this)), + surface_tractions(p.size(), p.getL()), + surface_displacements(p.size(), p.getL()), + surface_spectral_input(p.size(), p.getL()), + surface_spectral_output(p.size(), p.getL()), + surface_spectral_influence_disp(p.size(), p.getL()), + true_displacements(p.size(), p.getL()), + old_displacements(p.size(), p.getL()), gap(p.size(), p.getL()), + e_star(std::nan("")), tmp_coeff(1. / M_PI) { // this->setNumberOfThreads(this->nthreads); max_iterations = 5000; dump_freq = 100; this->functional->addFunctionalTerm(new ElasticEnergyFunctional(*this)); std::cerr << this << " is setting up the surfaces"; std::cerr << &p << " has size " << p.size() << std::endl; - } /* -------------------------------------------------------------------------- */ -BemFFTBase::~BemFFTBase() { - FFTPlanManager::get().clean(); -} +BemFFTBase::~BemFFTBase() { FFTPlanManager::get().clean(); } /* -------------------------------------------------------------------------- */ -const Surface & BemFFTBase::getTractions() const{ +const Surface& BemFFTBase::getTractions() const { return surface_tractions; } /* -------------------------------------------------------------------------- */ -const Surface & BemFFTBase::getDisplacements()const{ +const Surface& BemFFTBase::getDisplacements() const { return surface_displacements; } /* -------------------------------------------------------------------------- */ -const Surface & BemFFTBase::getSpectralInfluenceOverDisplacement(){ +const Surface& BemFFTBase::getSpectralInfluenceOverDisplacement() { return surface_spectral_influence_disp; } /* -------------------------------------------------------------------------- */ -void BemFFTBase::setEffectiveModulus(Real e_star){ +void BemFFTBase::setEffectiveModulus(Real e_star) { this->e_star = e_star; this->computeSpectralInfluenceOverDisplacement(); } /* -------------------------------------------------------------------------- */ -Real BemFFTBase::getEffectiveModulus(){ - return this->e_star; -} +Real BemFFTBase::getEffectiveModulus() { return this->e_star; } /* -------------------------------------------------------------------------- */ -void BemFFTBase::computeSpectralInfluenceOverDisplacement(){ - - STARTTIMER("computeSpectralInfluenceOverDisplacement"); - - if (std::isnan(tmp_coeff)) SURFACE_FATAL("constant tmp_coeff is nan"); - if (std::isnan(e_star)) SURFACE_FATAL("constant e_star is nan"); +void BemFFTBase::computeSpectralInfluenceOverDisplacement() { + // if (std::isnan(tmp_coeff)) SURFACE_FATAL("constant tmp_coeff is nan"); + // if (std::isnan(e_star)) SURFACE_FATAL("constant e_star is nan"); const Real L = surface.getL(); - auto wavevectors = - FFTransform:: - computeFrequencies(surface_spectral_influence_disp.sizes()); + auto wavevectors = FFTransform::computeFrequencies( + surface_spectral_influence_disp.sizes()); auto inf_it = surface_spectral_influence_disp.begin(), - inf_begin = surface_spectral_influence_disp.begin(); -#pragma omp parallel for firstprivate(inf_it) - for (auto it = wavevectors.begin(2) ; - it < wavevectors.end(2) ; - ++it) { + inf_begin = surface_spectral_influence_disp.begin(); + auto end = wavevectors.end(2); + //#pragma omp parallel for firstprivate(inf_it) + for (auto it = wavevectors.begin(2); it < end; ++it) { inf_it = inf_begin; inf_it += it - wavevectors.begin(2); VectorProxy q_vec(&(*it), 2); - q_vec *= 2*M_PI/L; + q_vec *= 2 * M_PI / L; Real q = q_vec.l2norm(); // Influence function *inf_it = 2. / (q * e_star); } surface_spectral_influence_disp(0) = 0.; - - STOPTIMER("computeSpectralInfluenceOverDisplacement"); - } - /* -------------------------------------------------------------------------- */ -void BemFFTBase::computeDisplacementsFromTractions(){ - - STARTTIMER("computeDisplacementsFromTractions"); - - this->applyInfluenceFunctions(surface_tractions,surface_displacements); - - STOPTIMER("computeDisplacementFromTractions"); - +void BemFFTBase::computeDisplacementsFromTractions() { + this->applyInfluenceFunctions(surface_tractions, surface_displacements); } /* -------------------------------------------------------------------------- */ -void BemFFTBase::computeTractionsFromDisplacements(){ - - STARTTIMER("computeDisplacementsFromTractions"); - - this->applyInverseInfluenceFunctions(surface_displacements,surface_tractions); - - STOPTIMER("computeDisplacementFromTractions"); - +void BemFFTBase::computeTractionsFromDisplacements() { + this->applyInverseInfluenceFunctions(surface_displacements, + surface_tractions); } - /* -------------------------------------------------------------------------- */ -void BemFFTBase::applyInfluenceFunctions(Surface & input, Surface & output){ - - STARTTIMER("applyInfluenceFunctions"); - - FFTransform & plan1 = FFTPlanManager::get().createPlan(input,surface_spectral_output); +void BemFFTBase::applyInfluenceFunctions(Surface& input, + Surface& output) { + FFTransform& plan1 = + FFTPlanManager::get().createPlan(input, surface_spectral_output); plan1.forwardTransform(); surface_spectral_output *= surface_spectral_influence_disp; - FFTransform & plan2 = FFTPlanManager::get().createPlan(output,surface_spectral_output); + FFTransform& plan2 = + FFTPlanManager::get().createPlan(output, surface_spectral_output); plan2.backwardTransform(); - - STOPTIMER("applyInfluenceFunctions"); - } /* -------------------------------------------------------------------------- */ -void BemFFTBase::applyInverseInfluenceFunctions(Surface & input, Surface & output){ - - STARTTIMER("applyInfluenceFunctions"); +void BemFFTBase::applyInverseInfluenceFunctions(Surface& input, + Surface& output) { - FFTransform & plan1 = FFTPlanManager::get().createPlan(input,surface_spectral_output); + FFTransform& plan1 = + FFTPlanManager::get().createPlan(input, surface_spectral_output); plan1.forwardTransform(); surface_spectral_output /= surface_spectral_influence_disp; surface_spectral_output(0) = 0; - FFTransform & plan2 = FFTPlanManager::get().createPlan(output,surface_spectral_output); + FFTransform& plan2 = + FFTPlanManager::get().createPlan(output, surface_spectral_output); plan2.backwardTransform(); - - STOPTIMER("applyInfluenceFunctions"); - } /* -------------------------------------------------------------------------- */ void BemFFTBase::computeGaps() { UInt size = surface.size(); #pragma omp parallel for - for (UInt i = 0 ; i < size*size ; i++) { + for (UInt i = 0; i < size * size; i++) { gap(i) = true_displacements(i) - surface(i); } } - /* -------------------------------------------------------------------------- */ -void BemFFTBase::computeTrueDisplacements(){ +void BemFFTBase::computeTrueDisplacements() { this->true_displacements = this->surface_displacements; UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; Real shift = 1e300; - - for (UInt i = 0; i < size; ++i) { - if (surface_displacements(i) - shift - surface(i) < 0.){ + if (surface_displacements(i) - shift - surface(i) < 0.) { shift = surface_displacements(i) - surface(i); } } for (UInt i = 0; i < size; ++i) { true_displacements(i) = surface_displacements(i) - shift; } - - - } /* -------------------------------------------------------------------------- */ -void BemFFTBase::addFunctional(Functional *new_funct) { +void BemFFTBase::addFunctional(Functional* new_funct) { this->functional->addFunctionalTerm(new_funct); } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_fft_base.hh b/src/bem/bem_fft_base.hh index da94f18..2a045b8 100644 --- a/src/bem/bem_fft_base.hh +++ b/src/bem/bem_fft_base.hh @@ -1,158 +1,154 @@ /** + * @file * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_FFT_BASE_H #define BEM_FFT_BASE_H /* -------------------------------------------------------------------------- */ +#include "bem_functional.hh" #include "bem_interface.hh" -#include -#include "surface_statistics.hh" -#include "fftransform.hh" #include "bem_meta_functional.hh" -#include "bem_functional.hh" +#include "fftransform.hh" +#include "surface_statistics.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemFFTBase : public BemInterface { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemFFTBase(Surface & p); + BemFFTBase(Surface& p); virtual ~BemFFTBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: - //! compute the displacement from traction input virtual void computeDisplacementsFromTractions(); //! compute the tractions from displacement input virtual void computeTractionsFromDisplacements(); //! apply influence funtions - virtual void applyInfluenceFunctions(Surface & input, Surface & output); + virtual void applyInfluenceFunctions(Surface& input, + Surface& output); //! apply inverse influence funtions - virtual void applyInverseInfluenceFunctions(Surface & input, Surface & output); + virtual void applyInverseInfluenceFunctions(Surface& input, + Surface& output); //! compute the influcence coefficients of pressure over displacement virtual void computeSpectralInfluenceOverDisplacement(); //! compute the displacements virtual void computeTrueDisplacements(); //! compute the gap virtual void computeGaps(); //! get the number of iterations virtual UInt getNbIterations() const = 0; //! get the convergence steps of iterations - virtual const std::vector & getConvergenceIterations() const = 0; - + virtual const std::vector& getConvergenceIterations() const = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! return the influcence coefficients - virtual const Surface & getSpectralInfluenceOverDisplacement(); + virtual const Surface& getSpectralInfluenceOverDisplacement(); //! return the actual tractions - virtual const Surface & getTractions() const; + virtual const Surface& getTractions() const; //! return the actual displacements - virtual const Surface & getDisplacements()const; + virtual const Surface& getDisplacements() const; //! get the computed true displacement - const Surface & getTrueDisplacements(){return true_displacements;}; + const Surface& getTrueDisplacements() { return true_displacements; }; //! get the computed gap - const Surface & getGap(){return gap;}; + const Surface& getGap() { return gap; }; //! set the elastic effective modulus void setEffectiveModulus(Real e_star); //! set the elastic effective modulus Real getEffectiveModulus(); //! set the maximal number of iterations - void setMaxIterations(UInt max_iter){this->max_iterations = max_iter;}; + void setMaxIterations(UInt max_iter) { this->max_iterations = max_iter; }; //! get the maximal number of iterations - UInt getMaxIterations(){return this->max_iterations;}; + UInt getMaxIterations() { return this->max_iterations; }; //! set dump freq - void setDumpFreq(UInt dump_freq){this->dump_freq = dump_freq;}; + void setDumpFreq(UInt dump_freq) { this->dump_freq = dump_freq; }; //! get dump freq - UInt getDumpFreq(){return this->dump_freq;}; + UInt getDumpFreq() { return this->dump_freq; }; //! set functional - void addFunctional(::tamaas::Functional * new_funct); + void addFunctional(::tamaas::Functional* new_funct); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! Functional for optimization - MetaFunctional * functional; + MetaFunctional* functional; //! surface tractions Surface surface_tractions; //! surface displacement Surface surface_displacements; //! surface input in spectral SurfaceComplex surface_spectral_input; //! surface output in spectral SurfaceComplex surface_spectral_output; //! surface influence coefficient over displacement Surface surface_spectral_influence_disp; //! shifted displacement in order to get the true displacement Surface true_displacements; //! old displacements (for stopping criterion) Surface old_displacements; //! computing of the gap Surface gap; //! Effective young modulus Real e_star; //! maximum of iterations UInt max_iterations; //! number of iterations UInt nb_iterations; //! number of iterations std::vector convergence_iterations; //! frequency at which to dump iteration info UInt dump_freq; /* ------------------------------------------------------------------------ */ /* temporary trick about some obscure scaling factor */ /* ------------------------------------------------------------------------ */ /* 0 2 = 2*1 1 4 = 2*2 2 10 = 2*5 3 20 = 2*10 4 34 = 2*12 */ //#define tmp_coeff (2.*n/M_PI) //#define tmp_coeff (n/M_PI) const Real tmp_coeff; - }; __END_TAMAAS__ #endif /* BEM_FFT_BASE_H */ diff --git a/src/bem/bem_functional.cpp b/src/bem/bem_functional.cpp index 413f5d6..984dcab 100644 --- a/src/bem/bem_functional.cpp +++ b/src/bem/bem_functional.cpp @@ -1,51 +1,44 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_functional.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -Functional::Functional(BemFFTBase & bem): - parameters(), - bem(bem), - gradF(NULL) -{} +Functional::Functional(BemFFTBase& bem) : parameters(), bem(bem), gradF(NULL) {} -Functional::~Functional() -{} +Functional::~Functional() {} -void Functional::setGradFPointer(Surface *p) { - this->gradF = p; -} +void Functional::setGradFPointer(Surface* p) { this->gradF = p; } -void Functional::copyParameters(const std::map ¶ms) { - auto it = params.begin(); - auto end = params.end(); - for (; it != end ; ++it) this->parameters.insert(*it); +void Functional::copyParameters(const std::map& params) { + // auto it = params.begin(); + // auto end = params.end(); + // for (; it != end ; ++it) this->parameters.insert(*it); } __END_TAMAAS__ diff --git a/src/bem/bem_functional.hh b/src/bem/bem_functional.hh index 94dc537..44e26b2 100644 --- a/src/bem/bem_functional.hh +++ b/src/bem/bem_functional.hh @@ -1,87 +1,91 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_FUNCTIONAL_HH__ #define __BEM_FUNCTIONAL_HH__ #include "surface.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ // forward declaration of BemFFTBase class BemFFTBase; /// Abstract class for functional interface definition class Functional { public: /// Constructor - explicit Functional(BemFFTBase & bem); + explicit Functional(BemFFTBase& bem); /// Destructor virtual ~Functional(); public: /// Compute value of objective function virtual Real computeF() = 0; /// Compute gradient of objective function (du) virtual void computeGradFU() = 0; /// Compute gradient of objective function (dp) virtual void computeGradFP() = 0; /// Set parameters - void setParameter(std::string name, Real new_p) { this->parameters[name] = new_p; } + void setParameter(std::string name, Real new_p) { + this->parameters[name] = new_p; + } /// Get parameters Real getParameter(std::string name) { return this->parameters[name]; } /// Get parameters map - const std::map & getParametersMap() const { return this->parameters; } + const std::map& getParametersMap() const { + return this->parameters; + } /// Copy parameters - void copyParameters(const std::map & params); + void copyParameters(const std::map& params); /// Set gradF pointer - void setGradFPointer(Surface * p); + void setGradFPointer(Surface* p); /// Get gradF surface - const Surface & getGradF() const { return *gradF; } + const Surface& getGradF() const { return *gradF; } protected: std::map parameters; - BemFFTBase & bem; + BemFFTBase& bem; - Surface * gradF; + Surface* gradF; }; __END_TAMAAS__ -#endif // __BEM_FUNCTIONAL_HH__ +#endif // __BEM_FUNCTIONAL_HH__ diff --git a/src/bem/bem_gigi.cpp b/src/bem/bem_gigi.cpp index 2957f35..49f8e89 100644 --- a/src/bem/bem_gigi.cpp +++ b/src/bem/bem_gigi.cpp @@ -1,321 +1,280 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include -#include "surface.hh" #include "bem_gigi.hh" -#include -#include +#include "surface.hh" #include #include +#include #include -#include -/* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -Real BemGigi::computeEquilibrium(Real epsilon, - Real mean_displacement) { +Real BemGigi::computeEquilibrium(Real epsilon, Real mean_displacement) { this->computeSpectralInfluenceOverDisplacement(); Real Rold = 1.; Real f = 1e300; this->search_direction = 0.; - this->true_displacements =0; + this->true_displacements = 0; this->true_displacements = mean_displacement; this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); this->computeGaps(); - - convergence_iterations.clear(); nb_iterations = 0; - max_iterations =50; - Real R=0; + max_iterations = 50; + Real R = 0; - while (f> epsilon && nb_iterations++ < max_iterations) { + while (f > epsilon && nb_iterations++ < max_iterations) { this->computeGaps(); this->functional->computeGradFU(); this->updateSearchDirection(R / Rold); Rold = R; Real alpha = this->computeOptimalStep(); - std::cout << "alpha vaut "<< alpha<< std::endl; + std::cout << "alpha vaut " << alpha << std::endl; - this->old_displacements=this->true_displacements; + this->old_displacements = this->true_displacements; this->updateDisplacements(alpha); this->computeGaps(); - this->optimizeToMeanDisplacement(mean_displacement); //espace admissible - this->computeGaps(); - this->computePressures(mean_displacement); - f=computeStoppingCriterion(); - -} + this->optimizeToMeanDisplacement(mean_displacement); // espace admissible + this->computeGaps(); + this->computePressures(mean_displacement); + f = computeStoppingCriterion(); + } this->computePressures(mean_displacement); - - return f; } /* -------------------------------------------------------------------------- */ Real BemGigi::computeStoppingCriterion() { + Real rho = this->functional->getParameter("rho"); + Real surface_energy = this->functional->getParameter("surface_energy"); - Real rho = this->functional->getParameter("rho"); - Real surface_energy = this->functional->getParameter("surface_energy"); - - - Real crit=0.; - //Real disp_norm = 0.; - - UInt n = surface.size(); - UInt size = n*n; - - //#pragma omp parallel for reduction(+:crit, disp_norm) -#pragma omp parallel for reduction(+:crit) - for (UInt i = 0; i < size; ++i) { - crit += std::abs(this->gap(i)*(this->surface_tractions(i)+surface_energy/rho * exp(- (gap(i)) / rho))); - - } + Real crit = 0.; + // Real disp_norm = 0.; + UInt n = surface.size(); + UInt size = n * n; + //#pragma omp parallel for reduction(+:crit, disp_norm) +#pragma omp parallel for reduction(+ : crit) + for (UInt i = 0; i < size; ++i) { + crit += + std::abs(this->gap(i) * (this->surface_tractions(i) + + surface_energy / rho * exp(-(gap(i)) / rho))); + } return crit; } /* -------------------------------------------------------------------------- */ - - /* -------------------------------------------------------------------------- */ void BemGigi::optimizeToMeanDisplacement(Real imposed_mean) { - Real target_value = imposed_mean - SurfaceStatistics::computeAverage(surface, 0); + Real target_value = + imposed_mean - SurfaceStatistics::computeAverage(surface, 0); UInt n = surface.size(); UInt size = n * n; // Initial guesses for upper and lower bound Real step_min = -10; Real step_max = 10; // Gaps for upper and lower bound Real gap_min = positiveGapAverage(step_min); Real gap_max = positiveGapAverage(step_max); UInt max_expansion = 8; // Expand bounds if necessary - for (UInt i = 0 ; gap_max < target_value && i < max_expansion ; i++, step_max *= 10) + for (UInt i = 0; gap_max < target_value && i < max_expansion; + i++, step_max *= 10) gap_max = positiveGapAverage(step_max); - for (UInt i = 0 ; gap_min > target_value && i < max_expansion ; i++, step_min *= 10) + for (UInt i = 0; gap_min > target_value && i < max_expansion; + i++, step_min *= 10) gap_min = positiveGapAverage(step_min); Real g = 0.; Real epsilon = 1e-12; Real step = 0; while (fabs(g - target_value) > epsilon) { step = (step_min + step_max) / 2.; g = positiveGapAverage(step); - if (g > target_value) step_max = step; - else if (g < target_value) step_min = step; + if (g > target_value) + step_max = step; + else if (g < target_value) + step_min = step; else { step_max = step; step_min = step; } } step = (step_min + step_max) / 2.; #pragma omp parallel for - for (UInt i = 0 ; i < size ; i++) { + for (UInt i = 0; i < size; i++) { gap(i) += step; - if (gap(i) < 0) gap(i) = 0; + if (gap(i) < 0) + gap(i) = 0; true_displacements(i) = gap(i) + surface(i); } } /* -------------------------------------------------------------------------- */ Real BemGigi::positiveGapAverage(Real shift) { UInt n = surface.size(); Real res = 0; -#pragma omp parallel for reduction(+: res) - for (UInt i = 0 ; i < n * n ; i++) { +#pragma omp parallel for reduction(+ : res) + for (UInt i = 0; i < n * n; i++) { Real shifted_gap = gap(i) + shift; res += shifted_gap * (shifted_gap > 0); } return res / (n * n); } - /* -------------------------------------------------------------------------- */ void BemGigi::updateSearchDirection(Real factor) { - STARTTIMER("updateSearchDirection"); - UInt n = surface.size(); - UInt size = n*n; - const Surface & gradF = this->functional->getGradF(); + UInt size = n * n; + const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->search_direction(i)= gradF(i); + this->search_direction(i) = gradF(i); } - - STOPTIMER("updateSearchDirection"); } - /* -------------------------------------------------------------------------- */ Real BemGigi::computeOptimalStep() { - STARTTIMER("computeOptimalStep"); - this->applyInverseInfluenceFunctions(search_direction, projected_direction); UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); Real numerator = 0., denominator = 0.; -#pragma omp parallel for reduction(+: numerator, denominator) +#pragma omp parallel for reduction(+ : numerator, denominator) for (UInt i = 0; i < size; ++i) { numerator += gradF(i) * search_direction(i); denominator += projected_direction(i) * search_direction(i); } Real alpha = numerator / denominator; - - STOPTIMER("computeOptimalStep"); return alpha; - - - } - /* -------------------------------------------------------------------------- */ -Real BemGigi::computeTau() { - return computeOptimalStep(); -} +Real BemGigi::computeTau() { return computeOptimalStep(); } /* -------------------------------------------------------------------------- */ void BemGigi::updateDisplacements(Real alpha) { - STARTTIMER("updateDisplacements"); - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) -= alpha*this->search_direction(i); - + this->true_displacements(i) -= alpha * this->search_direction(i); } - - STOPTIMER("updateDisplacements"); } - - - /* -------------------------------------------------------------------------- */ void BemGigi::emptyOverlap() { - STARTTIMER("emptyoverlap"); - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { if (gap(i) < 0) this->true_displacements(i) = this->surface(i); } - - STOPTIMER("emptyoverlap"); } /* -------------------------------------------------------------------------- */ void BemGigi::enforceMeanDisplacement(Real mean_displacement) { - STARTTIMER("enforceMeanDisplacement"); - UInt n = surface.size(); - UInt size = n*n; - Real moyenne_surface=SurfaceStatistics::computeAverage(this->surface, 0); + UInt size = n * n; + Real moyenne_surface = SurfaceStatistics::computeAverage(this->surface, 0); Real average = SurfaceStatistics::computeAverage(this->true_displacements, 0); - Real factor = (mean_displacement-moyenne_surface) / (average-moyenne_surface); + Real factor = + (mean_displacement - moyenne_surface) / (average - moyenne_surface); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) = factor*(this->true_displacements(i)-this->surface(i)) +this->surface(i); + this->true_displacements(i) = + factor * (this->true_displacements(i) - this->surface(i)) + + this->surface(i); } - - STOPTIMER("enforceMeanDisplacement"); } /* -------------------------------------------------------------------------- */ void BemGigi::computePressures(Real mean_displacement) { - this->computeTractionsFromDisplacements(); - UInt n = surface.size(); - UInt size = n*n; - Real rho = this->functional->getParameter("rho"); - Real surface_energy = this->functional->getParameter("surface_energy"); + UInt n = surface.size(); + UInt size = n * n; + Real rho = this->functional->getParameter("rho"); + Real surface_energy = this->functional->getParameter("surface_energy"); - Real mini=3000; - for (UInt i = 0; i < size; ++i) { - if (gap(i)surface_tractions(i)+surface_energy/rho surface_tractions(i)+surface_energy/rho ; + Real mini = 3000; + for (UInt i = 0; i < size; ++i) { + if (gap(i) < rho) { + if (this->surface_tractions(i) + surface_energy / rho < mini) + mini = this->surface_tractions(i) + surface_energy / rho; + } else { + if (this->surface_tractions(i) < mini) + mini = this->surface_tractions(i); } - else - { if (this->surface_tractions(i)surface_tractions(i) ;} } - this->surface_tractions-=mini; - + this->surface_tractions -= mini; } __END_TAMAAS__ diff --git a/src/bem/bem_gigi.hh b/src/bem/bem_gigi.hh index da40aa6..ff79b85 100644 --- a/src/bem/bem_gigi.hh +++ b/src/bem/bem_gigi.hh @@ -1,96 +1,92 @@ /** * * @author Valentine Rey * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_GIGI_H #define BEM_GIGI_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemGigi : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemGigi(Surface & p) : - BemFFTBase(p), - search_direction(p.size(), p.getL()), - projected_direction(p.size(), p.getL()), - mean_disp_search_direction(p.size(), p.getL()) { + BemGigi(Surface& p) + : BemFFTBase(p), search_direction(p.size(), p.getL()), + projected_direction(p.size(), p.getL()), + mean_disp_search_direction(p.size(), p.getL()) { e_star = 1.; max_iterations = 10000; }; virtual ~BemGigi(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: Real computeEquilibrium(Real epsilon, Real mean_displacement); void updateSearchDirection(Real factor); void updateDisplacements(Real tau); Real computeOptimalStep(); void emptyOverlap(); void enforceMeanDisplacement(Real mean_displacement); void computePressures(Real mean_displacement); Real computeStoppingCriterion(); void optimizeToMeanDisplacement(Real imposed_mean); Real positiveGapAverage(Real shift); - Real computeTau(); - /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! get the number of iterations - UInt getNbIterations() const{return this->nb_iterations;}; + UInt getNbIterations() const { return this->nb_iterations; }; //! get the convergence steps of iterations - const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + const std::vector& getConvergenceIterations() const { + return this->convergence_iterations; + }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! exploration direction for the Gigi algo Surface search_direction; //! projected exploration direction for the Gigi algo (fourier version) Surface projected_direction; //! exploration direction for optimization of mean displacement Surface mean_disp_search_direction; }; __END_TAMAAS__ #endif /* BEM_GIGI_H */ diff --git a/src/bem/bem_gigipol.cpp b/src/bem/bem_gigipol.cpp index 0ff66cc..551a5b6 100644 --- a/src/bem/bem_gigipol.cpp +++ b/src/bem/bem_gigipol.cpp @@ -1,882 +1,755 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include -#include "surface.hh" #include "bem_gigipol.hh" -#include -#include +#include "surface.hh" #include #include +#include #include -#include -/* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ void BemGigipol::computeTractionsFromDisplacements() { - this->applyInverseInfluenceFunctions(this->true_displacements,this->surface_tractions); + this->applyInverseInfluenceFunctions(this->true_displacements, + this->surface_tractions); } -Real BemGigipol::computeEquilibrium(Real epsilon, - Real mean_displacement) { - +Real BemGigipol::computeEquilibrium(Real epsilon, Real mean_displacement) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; - Real current_disp = SurfaceStatistics::computeAverage(true_displacements,0); - std::cout << "current disp "<computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); - std::ofstream file ("output.txt"); + std::ofstream file("output.txt"); this->computeGaps(); - convergence_iterations.clear(); - nb_iterations = 0;max_iterations=10000; + nb_iterations = 0; + max_iterations = 10000; - while(f > epsilon && nb_iterations < max_iterations) { + while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); - this->search_direction= this->functional->getGradF(); + this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); - this->search_direction -= gbar; + this->search_direction -= gbar; Real G = this->computeG(); - this->updateT(G,Gold,delta); + this->updateT(G, Gold, delta); Real tau = this->computeTau(); - this->old_displacements=this->true_displacements; + this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - this->true_displacements(i)-=tau*this->surface_t(i); + this->true_displacements(i) -= tau * this->surface_t(i); } - //Projection on admissible space + // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i)<0){ - this->true_displacements(i)=this->surface(i);} + if (this->gap(i) < 0) { + this->true_displacements(i) = this->surface(i); + } } this->computeGaps(); delta = this->updateDisplacements(tau, mean_displacement); - - //Projection on admissible space + // Projection on admissible space this->computeGaps(); this->enforceMeanDisplacement(mean_displacement); this->computeGaps(); this->computePressures(); - f=this->computeStoppingCriterion(); - - if (nb_iterations % dump_freq ==0){ - - - std::cout << "G vaut "<< G<< std::endl; - std::cout << "f vaut "<< f << std::endl; - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f << " " << f-fPrevious << " "<< 'G' << " " << G << " " - << std::endl; + f = this->computeStoppingCriterion(); + if (nb_iterations % dump_freq == 0) { + std::cout << "G vaut " << G << std::endl; + std::cout << "f vaut " << f << std::endl; + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f << " " << f - fPrevious << " " << 'G' << " " << G + << " " << std::endl; UInt n = surface.size(); - UInt size = n*n; - Real crit=0; - Real disp_norm=0; + UInt size = n * n; + Real crit = 0; + Real disp_norm = 0; for (UInt i = 0; i < size; ++i) { - crit += this->search_direction(i)*this->search_direction(i); - disp_norm += (true_displacements(i)*true_displacements(i)); - + crit += this->search_direction(i) * this->search_direction(i); + disp_norm += (true_displacements(i) * true_displacements(i)); } - - file<< std::scientific << std::setprecision(10)<< nb_iterations << " " - <computePressures(); - return f; } /* -------------------------------------------------------------------------- */ -Real BemGigipol::computeEquilibrium2(Real epsilon, - Real mean_pressure) { - +Real BemGigipol::computeEquilibrium2(Real epsilon, Real mean_pressure) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; - Real current_disp = SurfaceStatistics::computeAverage(surface,0.); + Real current_disp = SurfaceStatistics::computeAverage(surface, 0.); true_displacements = current_disp; this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i)<0){ - this->true_displacements(i)=this->surface(i);} + if (this->gap(i) < 0) { + this->true_displacements(i) = this->surface(i); + } } this->computeGaps(); - - // this->optimizeToMeanDisplacement(mean_displacement); - std::ofstream file ("output.txt"); - + std::ofstream file("output.txt"); convergence_iterations.clear(); - nb_iterations = 0;max_iterations=200000; + nb_iterations = 0; + max_iterations = 200000; - while(f > epsilon && nb_iterations < max_iterations) { + while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); - this->search_direction= this->functional->getGradF(); + this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); - this->search_direction += (2*mean_pressure+gbar); - - + this->search_direction += (2 * mean_pressure + gbar); Real G = this->computeG(); - - - - - - this->updateT(G,Gold,delta); + this->updateT(G, Gold, delta); Real tau = this->computeTau(mean_pressure); - this->old_displacements=this->true_displacements; + this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - this->true_displacements(i)-=tau*this->surface_t(i); + this->true_displacements(i) -= tau * this->surface_t(i); } - //Projection on admissible space + // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i)<0){ - this->true_displacements(i)=this->surface(i);} + if (this->gap(i) < 0) { + this->true_displacements(i) = this->surface(i); + } } this->computeGaps(); delta = this->updateDisplacements(tau, 0.); - - //Projection on admissible space + // Projection on admissible space this->computeGaps(); this->computePressures(); - f=this->computeStoppingCriterion(); + f = this->computeStoppingCriterion(); this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); - if (f< epsilon && epsilonsearch_direction(i)*this->search_direction(i); - disp_norm += (true_displacements(i)*true_displacements(i)); - + crit += this->search_direction(i) * this->search_direction(i); + disp_norm += (true_displacements(i) * true_displacements(i)); } - - file<< std::scientific << std::setprecision(10)<< nb_iterations << " " - <computePressures(); - return f; } /* -------------------------------------------------------------------------- */ -Real BemGigipol::computeEquilibrium2init(Real epsilon, - Real mean_pressure,Surface & init) { - +Real BemGigipol::computeEquilibrium2init(Real epsilon, Real mean_pressure, + Surface& init) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; - UInt n = surface.size(); - UInt size = n*n; - - this->true_displacements=init; - + UInt size = n * n; + this->true_displacements = init; this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i)<0){ - this->true_displacements(i)=this->surface(i);} + if (this->gap(i) < 0) { + this->true_displacements(i) = this->surface(i); + } } this->computeGaps(); - - std::ofstream file ("output.txt"); - - - - + std::ofstream file("output.txt"); convergence_iterations.clear(); - nb_iterations = 0;max_iterations=200000; + nb_iterations = 0; + max_iterations = 200000; - while(f > epsilon && nb_iterations < max_iterations) { + while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); - this->search_direction= this->functional->getGradF(); + this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); - this->search_direction += (2*mean_pressure+gbar); + this->search_direction += (2 * mean_pressure + gbar); Real G = this->computeG(); - - - this->updateT(G,Gold,delta); + this->updateT(G, Gold, delta); Real tau = this->computeTau(mean_pressure); - tau=0.01*tau; - this->old_displacements=this->true_displacements; + tau = 0.01 * tau; + this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - this->true_displacements(i)-=tau*this->surface_t(i); + this->true_displacements(i) -= tau * this->surface_t(i); } - //Projection on admissible space + // Projection on admissible space this->computeGaps(); - - - #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i)<0){ - this->true_displacements(i)=this->surface(i);} + if (this->gap(i) < 0) { + this->true_displacements(i) = this->surface(i); + } } this->computeGaps(); delta = this->updateDisplacements(tau, 0.); - - //Projection on admissible space + // Projection on admissible space this->computeGaps(); this->computePressures(); - f=this->computeStoppingCriterion(); + f = this->computeStoppingCriterion(); this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); + if (f < epsilon && epsilon < std::abs(min + mean_pressure)) + f = 3.; + if (nb_iterations % dump_freq == 0) { - if (f< epsilon && epsilonsearch_direction(i)*this->search_direction(i); - disp_norm += (true_displacements(i)*true_displacements(i)); - + crit += this->search_direction(i) * this->search_direction(i); + disp_norm += (true_displacements(i) * true_displacements(i)); } - - file<< std::scientific << std::setprecision(10)<< nb_iterations << " " - <computePressures(); - return f; } /* -------------------------------------------------------------------------- */ -Real BemGigipol::computeEquilibriuminit(Real epsilon, - Real mean_displacement,Surface & init) { - +Real BemGigipol::computeEquilibriuminit(Real epsilon, Real mean_displacement, + Surface& init) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; - this->true_displacements=init; - Real current_disp = SurfaceStatistics::computeAverage( this->true_displacements,0); - std::cout << "current disp "<true_displacements = init; + Real current_disp = + SurfaceStatistics::computeAverage(this->true_displacements, 0); + std::cout << "current disp " << current_disp << std::endl; if (current_disp == 0.) { true_displacements = mean_displacement; - std::cout << "je reinitialise "<computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); - std::ofstream file ("output.txt"); + std::ofstream file("output.txt"); this->computeGaps(); - convergence_iterations.clear(); - nb_iterations = 0;max_iterations=100000; + nb_iterations = 0; + max_iterations = 100000; - while(f > epsilon && nb_iterations < max_iterations) { + while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); - this->search_direction= this->functional->getGradF(); + this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); - this->search_direction -= gbar; + this->search_direction -= gbar; Real G = this->computeG(); - this->updateT(G,Gold,delta); + this->updateT(G, Gold, delta); Real tau = this->computeTau(); - this->old_displacements=this->true_displacements; + this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - this->true_displacements(i)-=tau*this->surface_t(i); + this->true_displacements(i) -= tau * this->surface_t(i); } - //Projection on admissible space + // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i)<0){ - this->true_displacements(i)=this->surface(i);} + if (this->gap(i) < 0) { + this->true_displacements(i) = this->surface(i); + } } this->computeGaps(); delta = this->updateDisplacements(tau, mean_displacement); - - //Projection on admissible space + // Projection on admissible space this->computeGaps(); this->enforceMeanDisplacement(mean_displacement); this->computeGaps(); this->computePressures(); - f=this->computeStoppingCriterion(); - - - if (nb_iterations % dump_freq ==0){ - - - std::cout << "G vaut "<< G<< std::endl; - std::cout << "f vaut "<< f << std::endl; - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f << " " << f-fPrevious << " "<< 'G' << " " << G << " " - << std::endl; + f = this->computeStoppingCriterion(); + if (nb_iterations % dump_freq == 0) { + std::cout << "G vaut " << G << std::endl; + std::cout << "f vaut " << f << std::endl; + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f << " " << f - fPrevious << " " << 'G' << " " << G + << " " << std::endl; UInt n = surface.size(); - UInt size = n*n; - Real crit=0; - Real disp_norm=0; + UInt size = n * n; + Real crit = 0; + Real disp_norm = 0; for (UInt i = 0; i < size; ++i) { - crit += this->search_direction(i)*this->search_direction(i); - disp_norm += (true_displacements(i)*true_displacements(i)); - + crit += this->search_direction(i) * this->search_direction(i); + disp_norm += (true_displacements(i) * true_displacements(i)); } - - file<< std::scientific << std::setprecision(10)<< nb_iterations << " " - <computePressures(); - return f; } /* -------------------------------------------------------------------------- */ - Real BemGigipol::computeStoppingCriterion() { - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; Real res = 0; - Real t_sum = std::abs(SurfaceStatistics::computeSum(this->true_displacements)); + Real t_sum = + std::abs(SurfaceStatistics::computeSum(this->true_displacements)); this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); - - -#pragma omp parallel for reduction(+:res) +#pragma omp parallel for reduction(+ : res) for (UInt i = 0; i < size; ++i) { - res += std::abs((gradF(i)-min)* ( this->true_displacements(i)-surface(i))); - - - + res += + std::abs((gradF(i) - min) * (this->true_displacements(i) - surface(i))); // res += // this->surface_tractions[i].real() // *(surface_displacements[i].real() - surface[i].real()); } - return res/std::abs(t_sum); + return res / std::abs(t_sum); } /* -------------------------------------------------------------------------- */ -Real BemGigipol::computeG(){ - STARTTIMER("computeG"); - +Real BemGigipol::computeG() { unsigned int n = surface.size(); - unsigned int size = n*n; + unsigned int size = n * n; Real res = 0.; -#pragma omp parallel for reduction(+: res) +#pragma omp parallel for reduction(+ : res) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) > 0.) { Real val = this->search_direction(i); - res += val*val;} + res += val * val; + } } - STOPTIMER("computeG"); return res; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -Real BemGigipol::computeMeanPressuresInNonContact(){ - STARTTIMER("computeMeanPressuresInNonContact"); - +Real BemGigipol::computeMeanPressuresInNonContact() { unsigned int n = surface.size(); - unsigned int size = n*n; + unsigned int size = n * n; Real res = 0.; UInt nb_contact = 0; -#pragma omp parallel for reduction(+: nb_contact,res) +#pragma omp parallel for reduction(+ : nb_contact, res) for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i) == 0. ) continue; + if (this->gap(i) == 0.) + continue; ++nb_contact; res += this->search_direction(i); } res /= nb_contact; - STOPTIMER("computeMeanPressuresInNonContact"); return res; } /* -------------------------------------------------------------------------- */ - void BemGigipol::optimizeToMeanDisplacement(Real imposed_mean) { - Real target_value = imposed_mean - SurfaceStatistics::computeAverage(surface, 0); + Real target_value = + imposed_mean - SurfaceStatistics::computeAverage(surface, 0); UInt n = surface.size(); UInt size = n * n; // Initial guesses for upper and lower bound Real step_min = -10; Real step_max = 10; // Gaps for upper and lower bound Real gap_min = positiveGapAverage(step_min); Real gap_max = positiveGapAverage(step_max); UInt max_expansion = 8; // Expand bounds if necessary - for (UInt i = 0 ; gap_max < target_value && i < max_expansion ; i++, step_max *= 10) + for (UInt i = 0; gap_max < target_value && i < max_expansion; + i++, step_max *= 10) gap_max = positiveGapAverage(step_max); - for (UInt i = 0 ; gap_min > target_value && i < max_expansion ; i++, step_min *= 10) + for (UInt i = 0; gap_min > target_value && i < max_expansion; + i++, step_min *= 10) gap_min = positiveGapAverage(step_min); Real g = 0.; Real epsilon = 1e-12; Real step = 0; while (fabs(g - target_value) > epsilon) { step = (step_min + step_max) / 2.; g = positiveGapAverage(step); - if (g > target_value) step_max = step; - else if (g < target_value) step_min = step; + if (g > target_value) + step_max = step; + else if (g < target_value) + step_min = step; else { step_max = step; step_min = step; } } step = (step_min + step_max) / 2.; #pragma omp parallel for - for (UInt i = 0 ; i < size ; i++) { + for (UInt i = 0; i < size; i++) { gap(i) += step; - if (gap(i) < 0) gap(i) = 0; + if (gap(i) < 0) + gap(i) = 0; true_displacements(i) = gap(i) + surface(i); } } /* -------------------------------------------------------------------------- */ Real BemGigipol::positiveGapAverage(Real shift) { UInt n = surface.size(); Real res = 0; -#pragma omp parallel for reduction(+: res) - for (UInt i = 0 ; i < n * n ; i++) { +#pragma omp parallel for reduction(+ : res) + for (UInt i = 0; i < n * n; i++) { Real shifted_gap = gap(i) + shift; res += shifted_gap * (shifted_gap > 0); } return res / (n * n); } - /* -------------------------------------------------------------------------- */ - -void BemGigipol::updateT(Real G, Real Gold, Real delta){ - STARTTIMER("updateT"); - +void BemGigipol::updateT(Real G, Real Gold, Real delta) { unsigned int n = surface.size(); - unsigned int size = n*n; - Real factor = delta*G/Gold; + unsigned int size = n * n; + Real factor = delta * G / Gold; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i) == 0.) this->surface_t(i) = 0.; - else{ + if (this->gap(i) == 0.) + this->surface_t(i) = 0.; + else { this->surface_t(i) *= factor; this->surface_t(i) += this->search_direction(i); } } - STOPTIMER("updateT"); } - - - /* -------------------------------------------------------------------------- */ Real BemGigipol::computeTau() { - STARTTIMER("computeOptimalStep"); - const UInt n = surface.size(); - const UInt size = n*n; + const UInt size = n * n; this->applyInverseInfluenceFunctions(surface_t, surface_r); Real rbar = 0; UInt nb_contact = 0; -#pragma omp parallel for reduction(+: nb_contact,rbar) +#pragma omp parallel for reduction(+ : nb_contact, rbar) for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i) == 0) continue; + if (this->gap(i) == 0) + continue; ++nb_contact; rbar += surface_r(i); } rbar /= nb_contact; surface_r -= rbar; - Real tau_sum1 = 0.,tau_sum2 = 0.; -#pragma omp parallel for reduction(+: tau_sum1, tau_sum2) + Real tau_sum1 = 0., tau_sum2 = 0.; +#pragma omp parallel for reduction(+ : tau_sum1, tau_sum2) for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i) == 0) continue; - tau_sum1 += this->search_direction(i)*surface_t(i); - tau_sum2 += surface_r(i)*surface_t(i); + if (this->gap(i) == 0) + continue; + tau_sum1 += this->search_direction(i) * surface_t(i); + tau_sum2 += surface_r(i) * surface_t(i); } - Real tau = tau_sum1/tau_sum2; + Real tau = tau_sum1 / tau_sum2; - STOPTIMER("computeTau"); return tau; } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeTau(Real mean_pressure) { - STARTTIMER("computeOptimalStep"); - const UInt n = surface.size(); - const UInt size = n*n; + const UInt size = n * n; this->applyInverseInfluenceFunctions(surface_t, surface_r); Real rbar = 0; UInt nb_contact = 0; -#pragma omp parallel for reduction(+: nb_contact,rbar) +#pragma omp parallel for reduction(+ : nb_contact, rbar) for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i) == 0) continue; + if (this->gap(i) == 0) + continue; ++nb_contact; rbar += surface_r(i); } rbar /= nb_contact; - surface_r += 2*mean_pressure+rbar; + surface_r += 2 * mean_pressure + rbar; - Real tau_sum1 = 0.,tau_sum2 = 0.; -#pragma omp parallel for reduction(+: tau_sum1, tau_sum2) + Real tau_sum1 = 0., tau_sum2 = 0.; +#pragma omp parallel for reduction(+ : tau_sum1, tau_sum2) for (unsigned int i = 0; i < size; ++i) { - if (this->gap(i) == 0) continue; - tau_sum1 += this->search_direction(i)*surface_t(i); - tau_sum2 += surface_r(i)*surface_t(i); + if (this->gap(i) == 0) + continue; + tau_sum1 += this->search_direction(i) * surface_t(i); + tau_sum2 += surface_r(i) * surface_t(i); } - Real tau = tau_sum1/tau_sum2; + Real tau = tau_sum1 / tau_sum2; - STOPTIMER("computeTau"); return tau; } /* -------------------------------------------------------------------------- */ - Real BemGigipol::updateDisplacements(Real tau, Real mean_displacement) { - STARTTIMER("updateDisplacements"); - - - unsigned int n = surface.size(); - unsigned int size = n*n; - - + unsigned int size = n * n; - //compute number of interpenetration without contact + // compute number of interpenetration without contact UInt nb_iol = 0; -#pragma omp parallel for reduction(+: nb_iol) +#pragma omp parallel for reduction(+ : nb_iol) for (unsigned int i = 0; i < size; ++i) { - if ( this->search_direction(i) <0 && this->gap(i) == 0.){ + if (this->search_direction(i) < 0 && this->gap(i) == 0.) { - this->true_displacements(i) -= tau* this->search_direction(i); + this->true_displacements(i) -= tau * this->search_direction(i); ++nb_iol; } } Real delta = 0; - if (nb_iol > 0) delta = 0.; - else delta = 1.; - + if (nb_iol > 0) + delta = 0.; + else + delta = 1.; return delta; - - - - - STOPTIMER("updateDisplacements"); } /* -------------------------------------------------------------------------- */ void BemGigipol::enforceMeanDisplacement(Real mean_displacement) { - STARTTIMER("enforceMeanDisplacement"); - UInt n = surface.size(); - UInt size = n*n; - Real moyenne_surface=SurfaceStatistics::computeAverage(this->surface, 0); + UInt size = n * n; + Real moyenne_surface = SurfaceStatistics::computeAverage(this->surface, 0); Real average = SurfaceStatistics::computeAverage(this->true_displacements, 0); - Real factor = (mean_displacement-moyenne_surface) / (average-moyenne_surface); + Real factor = + (mean_displacement - moyenne_surface) / (average - moyenne_surface); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) = factor*(this->true_displacements(i)-this->surface(i)) +this->surface(i); + this->true_displacements(i) = + factor * (this->true_displacements(i) - this->surface(i)) + + this->surface(i); } - - STOPTIMER("enforceMeanDisplacement"); } /* -------------------------------------------------------------------------- */ - void BemGigipol::computePressures() { this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); this->surface_tractions -= min; - } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_gigipol.hh b/src/bem/bem_gigipol.hh index 1e803c2..79518d4 100644 --- a/src/bem/bem_gigipol.hh +++ b/src/bem/bem_gigipol.hh @@ -1,105 +1,104 @@ /** * * @author Valentine Rey * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_GIGIPOL_H #define BEM_GIGIPOL_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemGigipol : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemGigipol(Surface & p) : - BemFFTBase(p), - search_direction(p.size(), p.getL()), - mean_disp_search_direction(p.size(), p.getL()), - surface_t(p.size(),p.getL()), - surface_r(p.size(),p.getL()), - pold(p.size(),p.getL()){ + BemGigipol(Surface& p) + : BemFFTBase(p), search_direction(p.size(), p.getL()), + mean_disp_search_direction(p.size(), p.getL()), + surface_t(p.size(), p.getL()), surface_r(p.size(), p.getL()), + pold(p.size(), p.getL()) { e_star = 1.; max_iterations = 10000; } - virtual ~BemGigipol(){} + virtual ~BemGigipol() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: Real computeEquilibrium(Real epsilon, Real mean_displacement); - Real computeEquilibrium2(Real epsilon, Real mean_pressure); - Real computeEquilibrium2init(Real epsilon,Real mean_pressure, Surface & init); - Real computeEquilibriuminit(Real epsilon,Real mean_displacement, Surface & init); + Real computeEquilibrium2(Real epsilon, Real mean_pressure); + Real computeEquilibrium2init(Real epsilon, Real mean_pressure, + Surface& init); + Real computeEquilibriuminit(Real epsilon, Real mean_displacement, + Surface& init); Real computeStoppingCriterion(); Real computeG(); Real computeMeanPressuresInNonContact(); void optimizeToMeanDisplacement(Real imposed_mean); Real positiveGapAverage(Real shift); void updateT(Real G, Real Gold, Real delta); Real updateDisplacements(Real tau, Real mean_displacement); void enforceMeanDisplacement(Real mean_displacement); void computePressures(); Real computeTau(); - Real computeTau(Real mean_pressure); + Real computeTau(Real mean_pressure); virtual void computeTractionsFromDisplacements(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! get the number of iterations - UInt getNbIterations() const{return this->nb_iterations;}; + UInt getNbIterations() const { return this->nb_iterations; }; //! get the convergence steps of iterations - const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + const std::vector& getConvergenceIterations() const { + return this->convergence_iterations; + }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! exploration direction for the Gigi algo Surface search_direction; //! exploration direction for optimization of mean displacement Surface mean_disp_search_direction; //! exploration direction for the polonski algo Surface surface_t; //! projected exploration direction for the polonski algo Surface surface_r; //! previous pressure Surface pold; }; __END_TAMAAS__ #endif /* BEM_GIGIPOL_H */ diff --git a/src/bem/bem_grid.cpp b/src/bem/bem_grid.cpp index 486e4c3..7db631c 100644 --- a/src/bem/bem_grid.cpp +++ b/src/bem/bem_grid.cpp @@ -1,436 +1,443 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_grid.hh" +#include "fft_plan_manager.hh" #include "grid.hh" #include "types.hh" -#include "fft_plan_manager.hh" -#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -BemGrid::BemGrid(Surface & surface): - E(1.), - nu(0.3), - surface(surface), - surface_normals(surface.sizes(), 3), - tractions(surface.sizes(), 3), - displacements(surface.sizes(), 3), - gaps(surface.sizes(), 3), - true_tractions(NULL), - true_displacements(NULL), - dump_freq(100) -{ +BemGrid::BemGrid(Surface& surface) + : E(1.), nu(0.3), surface(surface), surface_normals(surface.sizes(), 3), + tractions(surface.sizes(), 3), displacements(surface.sizes(), 3), + gaps(surface.sizes(), 3), true_tractions(NULL), true_displacements(NULL), + dump_freq(100) { auto hermitian_sizes = - GridHermitian::hermitianDimensions(surface.sizes()); + GridHermitian::hermitianDimensions(surface.sizes()); influence.setNbComponents(9); spectral_tractions.setNbComponents(3); spectral_displacements.setNbComponents(3); influence.resize(hermitian_sizes); spectral_tractions.resize(hermitian_sizes); spectral_displacements.resize(hermitian_sizes); - //computeSurfaceNormals(); + // computeSurfaceNormals(); } /* -------------------------------------------------------------------------- */ BemGrid::~BemGrid() { FFTPlanManager::get().clean(); delete true_tractions; delete true_displacements; } /* -------------------------------------------------------------------------- */ -const Grid2dReal & BemGrid::getTrueTractions() const { - if (true_tractions == NULL) TAMAAS_EXCEPTION("True tractions were not allocated"); +const Grid& BemGrid::getTrueTractions() const { + if (true_tractions == NULL) + TAMAAS_EXCEPTION("True tractions were not allocated"); return *true_tractions; } -const Grid2dReal & BemGrid::getTrueDisplacements() const { - if (true_displacements == NULL) TAMAAS_EXCEPTION("True displacements were not allocated"); +const Grid& BemGrid::getTrueDisplacements() const { + if (true_displacements == NULL) + TAMAAS_EXCEPTION("True displacements were not allocated"); return *true_displacements; } /* -------------------------------------------------------------------------- */ -/// This function computes surface slopes in fourier space and fills the normals grid +/// This function computes surface slopes in fourier space and fills the normals +/// grid void BemGrid::computeSurfaceNormals() { SurfaceComplex spectral_surface(surface.size(), surface.getL()); GridHermitian spectral_slopes(spectral_surface.sizes(), 3); - FFTransform & plan1 = FFTPlanManager::get().createPlan(surface, spectral_surface); - FFTransform & plan2 = FFTPlanManager::get().createPlan(surface_normals, spectral_slopes); + FFTransform& plan1 = + FFTPlanManager::get().createPlan(surface, spectral_surface); + FFTransform& plan2 = + FFTPlanManager::get().createPlan(surface_normals, spectral_slopes); plan1.forwardTransform(); // Loops should be with signed integers std::array n; - std::copy(spectral_surface.sizes().begin(), - spectral_surface.sizes().end(), - n.begin()); - constexpr Complex I(0, 1); + std::copy(spectral_surface.sizes().begin(), spectral_surface.sizes().end(), + n.begin()); + const Complex I(0, 1); #pragma omp parallel -{ + { #pragma omp for collapse(2) - for (Int i = 0 ; i <= n[0] / 2 ; i++) { - for (Int j = 0 ; j < n[1] ; j++) { - Real q1 = 2*M_PI*j; - Real q2 = 2*M_PI*i; - spectral_slopes(i, j, 0) = -q1*I*spectral_surface(i, j); - spectral_slopes(i, j, 1) = -q2*I*spectral_surface(i, j); - spectral_slopes(i, j, 2) = 0; + for (Int i = 0; i <= n[0] / 2; i++) { + for (Int j = 0; j < n[1]; j++) { + Real q1 = 2 * M_PI * j; + Real q2 = 2 * M_PI * i; + spectral_slopes(i, j, 0) = -q1 * I * spectral_surface(i, j); + spectral_slopes(i, j, 1) = -q2 * I * spectral_surface(i, j); + spectral_slopes(i, j, 2) = 0; + } } - } #pragma omp for collapse(2) - for (Int i = n[0]/2 + 1 ; i < n[0] ; i++) { - for (Int j = 0 ; j < n[1] ; j++) { - Real q1 = 2*M_PI*j; - Real q2 = 2*M_PI*(i-n[0]); - spectral_slopes(i, j, 0) = -q1*I*spectral_surface(i, j); - spectral_slopes(i, j, 1) = -q2*I*spectral_surface(i, j); - spectral_slopes(i, j, 2) = 0; + for (Int i = n[0] / 2 + 1; i < n[0]; i++) { + for (Int j = 0; j < n[1]; j++) { + Real q1 = 2 * M_PI * j; + Real q2 = 2 * M_PI * (i - n[0]); + spectral_slopes(i, j, 0) = -q1 * I * spectral_surface(i, j); + spectral_slopes(i, j, 1) = -q2 * I * spectral_surface(i, j); + spectral_slopes(i, j, 2) = 0; + } } - } -} // end #pragma omp parallel + } // end #pragma omp parallel // Dirac - spectral_slopes(0, 0, 2) = n[0]*n[0]; + spectral_slopes(0, 0, 2) = n[0] * n[0]; plan2.backwardTransform(); FFTPlanManager::get().destroyPlan(surface, spectral_surface); FFTPlanManager::get().destroyPlan(surface_normals, spectral_slopes); // Make surface normal VectorProxy sn(nullptr, 3); const UInt N = surface_normals.getNbPoints(); #pragma omp parallel for firstprivate(sn) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { sn.setPointer(surface_normals.getInternalData() + i * sn.dataSize()); sn /= sn.l2norm(); } } /* -------------------------------------------------------------------------- */ void BemGrid::computeDisplacementsFromTractions() { applyInfluenceFunctions(tractions, displacements); } void BemGrid::computeTractionsFromDisplacements() { applyInverseInfluenceFunctions(tractions, displacements); } /* -------------------------------------------------------------------------- */ -void BemGrid::computeGaps(Grid &disp) { +void BemGrid::computeGaps(Grid& disp) { auto n = surface.sizes(); #pragma omp parallel for collapse(2) - for (UInt i = 0 ; i < n[0] ; i++) { - for (UInt j = 0 ; j < n[1] ; j++) { + for (UInt i = 0; i < n[0]; i++) { + for (UInt j = 0; j < n[1]; j++) { gaps(i, j, 0) = disp(i, j, 0); gaps(i, j, 1) = disp(i, j, 1); gaps(i, j, 2) = disp(i, j, 2) - surface(i, j); } } } /* -------------------------------------------------------------------------- */ -void BemGrid::applyInfluenceFunctions(Grid & input, Grid & output) { - TAMAAS_ASSERT(input.dataSize() == output.dataSize(), "input and output have different size"); - FFTransform & plan_1 = FFTPlanManager::get().createPlan(input, spectral_tractions); - FFTransform & plan_2 = FFTPlanManager::get().createPlan(output, spectral_displacements); +void BemGrid::applyInfluenceFunctions(Grid& input, + Grid& output) { + TAMAAS_ASSERT(input.dataSize() == output.dataSize(), + "input and output have different size"); + FFTransform& plan_1 = + FFTPlanManager::get().createPlan(input, spectral_tractions); + FFTransform& plan_2 = + FFTPlanManager::get().createPlan(output, spectral_displacements); plan_1.forwardTransform(); - Complex - *F = influence.getInternalData(), - *p = spectral_tractions.getInternalData(), - *u = spectral_displacements.getInternalData(); - VectorProxy - spectral_p(nullptr, 3), - spectral_u(nullptr, 3); - MatrixProxy - spectral_F(nullptr, 3, 3); + Complex *F = influence.getInternalData(), + *p = spectral_tractions.getInternalData(), + *u = spectral_displacements.getInternalData(); + VectorProxy spectral_p(nullptr, 3), spectral_u(nullptr, 3); + MatrixProxy spectral_F(nullptr, 3, 3); spectral_displacements = 0; const UInt N = influence.getNbPoints(); // OpenMP not very cool with this: best to have a POD iteration variable #pragma omp parallel for firstprivate(spectral_p, spectral_u, spectral_F) - for (UInt i = 0 ; i < N ; ++i) { + for (UInt i = 0; i < N; ++i) { spectral_p.setPointer(p + i * spectral_p.dataSize()); spectral_u.setPointer(u + i * spectral_u.dataSize()); spectral_F.setPointer(F + i * spectral_F.dataSize()); spectral_u.mul(spectral_F, spectral_p); } plan_2.backwardTransform(); } /* -------------------------------------------------------------------------- */ -void BemGrid::applyInverseInfluenceFunctions(Grid & input [[gnu::unused]], - Grid & output[[gnu::unused]]) { +void BemGrid::applyInverseInfluenceFunctions( + Grid& input[[gnu::unused]], Grid& output[[gnu::unused]]) { TAMAAS_EXCEPTION("applyInverseInfluenceFunctions not yet implemented"); } /* -------------------------------------------------------------------------- */ // warning: this function will suck your soul out // loops must be written with signed integers void BemGrid::computeInfluence() { // Iterator over points of surface MatrixProxy it(influence.getInternalData(), 3, 3); // Imaginary unit - constexpr Complex I(0, 1); + const Complex I(0, 1); const Int size = this->surface.size(); - const Real L_1 = 1.; // this->surface.lengths()[0]; - const Real L_2 = 1.; // this->surface.lengths()[1]; + const Real L_1 = 1.; // this->surface.lengths()[0]; + const Real L_2 = 1.; // this->surface.lengths()[1]; this->influence = 0; // Influence functions matrix, ask Lucas -#define INFLUENCE(q_1, q_2, q, E, nu) { \ - 2./(E*q*q*q)*(-nu*nu*q_1*q_1 - nu*q_2*q_2 + q*q), \ - -q_1*q_2/(E*q*q*q)*(1+nu)*2*nu, \ - I*q_1/(E*q*q)*(1+nu)*(1-2*nu), \ - -q_1*q_2/(E*q*q*q)*(1+nu)*2*nu, \ - 2./(E*q*q*q)*(-nu*nu*q_2*q_2 - nu*q_1*q_1 + q*q), \ - I*q_2/(E*q*q)*(1+nu)*(1-2*nu), \ - -I*q_1/(E*q*q)*(1+nu)*(1-2*nu), \ - -I*q_2/(E*q*q)*(1+nu)*(1-2*nu), \ - 2./(E*q)*(1-nu*nu)} +#define INFLUENCE(q_1, q_2, q, E, nu) \ + { \ + 2. / (E * q * q * q) * (-nu * nu * q_1 * q_1 - nu * q_2 * q_2 + q * q), \ + -q_1 *q_2 / (E * q * q * q) * (1 + nu) * 2 * nu, \ + I *q_1 / (E * q * q) * (1 + nu) * (1 - 2 * nu), \ + -q_1 *q_2 / (E * q * q * q) * (1 + nu) * 2 * nu, \ + 2. / (E * q * q * q) * \ + (-nu * nu * q_2 * q_2 - nu * q_1 * q_1 + q * q), \ + I *q_2 / (E * q * q) * (1 + nu) * (1 - 2 * nu), \ + -I *q_1 / (E * q * q) * (1 + nu) * (1 - 2 * nu), \ + -I *q_2 / (E * q * q) * (1 + nu) * (1 - 2 * nu), \ + 2. / (E * q) * (1 - nu * nu) \ + } // Fill influence for single point -#define FILL_INFLUENCE(k, l) do { \ - Real q_1 = 2*M_PI*(l)/L_1; \ - Real q_2 = 2*M_PI*(k)/L_2; \ - Real q = std::sqrt(q_1*q_1+q_2*q_2); \ - Complex influence_1[] = INFLUENCE(q_1, q_2, q, E, nu); \ - MatrixProxy inf_mat(influence_1, 3, 3); \ - it.setPointer(&influence(i, j, 0)); \ - it = inf_mat; \ - } while(0) +#define FILL_INFLUENCE(k, l) \ + do { \ + Real q_1 = 2 * M_PI * (l) / L_1; \ + Real q_2 = 2 * M_PI * (k) / L_2; \ + Real q = std::sqrt(q_1 * q_1 + q_2 * q_2); \ + Complex influence_1[] = INFLUENCE(q_1, q_2, q, E, nu); \ + MatrixProxy inf_mat(influence_1, 3, 3); \ + it.setPointer(&influence(i, j, 0)); \ + it = inf_mat; \ + } while (0) // Fill influence points for "symetric" areas -#define FILL_SYM_INFLUENCE(k, l) do { \ - Real q_1 = 2*M_PI*(l)/L_1; \ - Real q_2 = 2*M_PI*(k)/L_2; \ - Real q = std::sqrt(q_1*q_1+q_2*q_2); \ - Complex influence_1[] = INFLUENCE(q_1, q_2, q, E, nu); \ - Complex influence_2[] = INFLUENCE(q_2, q_1, q, E, nu); \ - MatrixProxy inf_mat(influence_1, 3, 3); \ - it.setPointer(&influence(i, j, 0)); \ - it = inf_mat; \ - inf_mat.setPointer(influence_2); \ - it.setPointer(&influence(j, i, 0)); \ - it = inf_mat; \ - } while(0) - -#pragma omp parallel firstprivate(it) // all the following loops are independent -{ +#define FILL_SYM_INFLUENCE(k, l) \ + do { \ + Real q_1 = 2 * M_PI * (l) / L_1; \ + Real q_2 = 2 * M_PI * (k) / L_2; \ + Real q = std::sqrt(q_1 * q_1 + q_2 * q_2); \ + Complex influence_1[] = INFLUENCE(q_1, q_2, q, E, nu); \ + Complex influence_2[] = INFLUENCE(q_2, q_1, q, E, nu); \ + MatrixProxy inf_mat(influence_1, 3, 3); \ + it.setPointer(&influence(i, j, 0)); \ + it = inf_mat; \ + inf_mat.setPointer(influence_2); \ + it.setPointer(&influence(j, i, 0)); \ + it = inf_mat; \ + } while (0) + +#pragma omp parallel firstprivate( \ + it) // all the following loops are independent + { // Loops over parts of surface /* [ ][ ][ ][ ] [ ][x][ ][ ] [ ][ ][ ][ ] [ ][ ][ ][o] */ -#pragma omp for schedule(dynamic) // can't collapse triangluar loops - for (Int i = 1 ; i < size/2 ; i++) { - for (Int j = i ; j < size/2 ; j++) { - FILL_SYM_INFLUENCE(i, j); +#pragma omp for schedule(dynamic) // can't collapse triangluar loops + for (Int i = 1; i < size / 2; i++) { + for (Int j = i; j < size / 2; j++) { + FILL_SYM_INFLUENCE(i, j); + } } - } - /* - [ ][ ][ ][ ] - [ ][ ][ ][o] - [ ][ ][ ][ ] - [ ][x][ ][ ] - */ + /* + [ ][ ][ ][ ] + [ ][ ][ ][o] + [ ][ ][ ][ ] + [ ][x][ ][ ] + */ #pragma omp for collapse(2) - for (Int i = size/2+1 ; i < size ; i++) { - for (Int j = 1 ; j < size/2 ; j++) { - FILL_INFLUENCE(i-size, j); + for (Int i = size / 2 + 1; i < size; i++) { + for (Int j = 1; j < size / 2; j++) { + FILL_INFLUENCE(i - size, j); + } } - } - /* - [ ][x][x][o] - [x][ ][x][ ] - [x][x][x][ ] - [ ][ ][ ][ ] - */ + /* + [ ][x][x][o] + [x][ ][x][ ] + [x][x][x][ ] + [ ][ ][ ][ ] + */ #pragma omp for - for (Int i = 1 ; i <= size/2 ; i++) { - { - Int j = size/2; - FILL_SYM_INFLUENCE(i, j); - } { - Int j = 0; - FILL_SYM_INFLUENCE(i, j); + for (Int i = 1; i <= size / 2; i++) { + { + Int j = size / 2; + FILL_SYM_INFLUENCE(i, j); + } + { + Int j = 0; + FILL_SYM_INFLUENCE(i, j); + } } - } - /* - [ ][ ][ ][ ] - [ ][ ][ ][ ] - [ ][ ][ ][o] - [x][ ][x][ ] - */ + /* + [ ][ ][ ][ ] + [ ][ ][ ][ ] + [ ][ ][ ][o] + [x][ ][x][ ] + */ #pragma omp for - for (Int i = size/2+1 ; i < size ; i++) { - { - Int j = size/2; - FILL_INFLUENCE(i-size, j); - } { - Int j = 0; - FILL_INFLUENCE(i-size, j); + for (Int i = size / 2 + 1; i < size; i++) { + { + Int j = size / 2; + FILL_INFLUENCE(i - size, j); + } + { + Int j = 0; + FILL_INFLUENCE(i - size, j); + } } - } -} // End #pragma omp parallel - /* State of surface now: - [0][x][x][o] - [x][x][x][o] - [x][x][x][o] - [x][x][x][o] - - Legend: x => explicitely filled - o => hermitian symetry - 0 => actually 0 - */ - - computeInfluenceLipschitz(); + } // End #pragma omp parallel + /* State of surface now: + [0][x][x][o] + [x][x][x][o] + [x][x][x][o] + [x][x][x][o] + + Legend: x => explicitely filled + o => hermitian symetry + 0 => actually 0 + */ + + computeInfluenceLipschitz(); #undef INFLUENCE #undef FILL_INFLUENCE #undef FILL_SYM_INFLUENCE } /* -------------------------------------------------------------------------- */ /// Computing L_2 norm of influence functions void BemGrid::computeInfluenceLipschitz() { const UInt N = influence.getNbPoints(); VectorProxy m(nullptr, 9); - Real norm = 0.; + Real _norm = 0.; -#pragma omp parallel for firstprivate(m) reduction(+:norm) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp parallel for firstprivate(m) reduction(+ : _norm) + for (UInt i = 0; i < N; i++) { m.setPointer(influence.getInternalData() + i * m.dataSize()); - norm += std::pow(std::norm(m.l2norm()), 2); + _norm += pow(norm(m.l2norm()), 2); } - lipschitz = std::sqrt(norm); + lipschitz = sqrt(_norm); } /* -------------------------------------------------------------------------- */ /* Friction related computations */ /* -------------------------------------------------------------------------- */ -void BemGrid::projectOnFrictionCone(Grid & field, Real mu) { +void BemGrid::projectOnFrictionCone(Grid& field, Real mu) { VectorProxy p_proxy(nullptr, 3); const UInt N = field.getNbPoints(); #pragma omp parallel for firstprivate(p_proxy) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { p_proxy.setPointer(field.getInternalData() + i * p_proxy.dataSize()); projectOnFrictionCone(p_proxy, mu); } } /* -------------------------------------------------------------------------- */ -void BemGrid::enforceMeanValue(Grid & field, - const Grid & target) { +void BemGrid::enforceMeanValue(Grid& field, + const Grid& target) { Real red_0 = 0, red_1 = 0, red_2 = 0; auto n = field.sizes(); -#pragma omp parallel for collapse(2) reduction(+:red_0, red_1, red_2) - for (UInt i = 0 ; i < n[0] ; i++) { - for (UInt j = 0 ; j < n[1] ; j++) { +#pragma omp parallel for collapse(2) reduction(+ : red_0, red_1, red_2) + for (UInt i = 0; i < n[0]; i++) { + for (UInt j = 0; j < n[1]; j++) { red_0 += field(i, j, 0); red_1 += field(i, j, 1); red_2 += field(i, j, 2); } } - red_0 /= n[0]*n[1]; red_1 /= n[0]*n[1]; red_2 /= n[0]*n[1]; + red_0 /= n[0] * n[1]; + red_1 /= n[0] * n[1]; + red_2 /= n[0] * n[1]; Real p1_data[3] = {red_0, red_1, red_2}; // Loop for pressure shifting VectorProxy p1(p1_data, 3); VectorProxy p0((Real*)target.getInternalData(), 3); VectorProxy p(nullptr, 3); const UInt N = field.getNbPoints(); #pragma omp parallel for firstprivate(p0, p1) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { p.setPointer(field.getInternalData() + i * p.dataSize()); p -= p1; p += p0; } } /* -------------------------------------------------------------------------- */ -void BemGrid::computeMeanValueError(Grid & field, - const Grid & target, - Grid & error_vec) { +void BemGrid::computeMeanValueError(Grid& field, + const Grid& target, + Grid& error_vec) { Real p0 = 0, p1 = 0, p2 = 0; auto n = field.sizes(); -#pragma omp parallel for collapse(2) reduction(+:p0, p1, p2) - for (UInt i = 0 ; i < n[0] ; i++) { - for (UInt j = 0 ; j < n[1] ; j++) { +#pragma omp parallel for collapse(2) reduction(+ : p0, p1, p2) + for (UInt i = 0; i < n[0]; i++) { + for (UInt j = 0; j < n[1]; j++) { p0 += field(i, j, 0); p1 += field(i, j, 1); p2 += field(i, j, 2); } } - p0 /= n[0]*n[1]; p1 /= n[0]*n[1]; p2 /= n[0]*n[1]; + p0 /= n[0] * n[1]; + p1 /= n[0] * n[1]; + p2 /= n[0] * n[1]; Real error[3] = {p0 - target(0), p1 - target(1), p2 - target(2)}; VectorProxy e(error, 3); error_vec = e; } /* -------------------------------------------------------------------------- */ -Real BemGrid::computeMeanValueError(Grid & field, const Grid & target) { +Real BemGrid::computeMeanValueError(Grid& field, + const Grid& target) { Real e[3] = {0.}; VectorProxy error(e, 3); computeMeanValueError(field, target, error); Real norm = - target(0)*target(0) - + target(1)*target(1) - + target(2)*target(2); + target(0) * target(0) + target(1) * target(1) + target(2) * target(2); return error.l2norm() / std::sqrt(norm); } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_grid.hh b/src/bem/bem_grid.hh index 56da363..5ca4fd4 100644 --- a/src/bem/bem_grid.hh +++ b/src/bem/bem_grid.hh @@ -1,184 +1,183 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_GRID_HH__ #define __BEM_GRID_HH__ /* -------------------------------------------------------------------------- */ -#include "surface.hh" #include "grid.hh" +#include "surface.hh" #include "types.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ - -// Necessary typedefs for swig -typedef Grid Grid2dReal; -typedef Grid Grid2dComplex; -typedef Grid Grid2dUInt; -typedef GridHermitian GridHermitian2dReal; - /** * @brief abstract class for BEMs that use multi component fields */ class BemGrid { public: /// Constructor - BemGrid(Surface & surface); + BemGrid(Surface& surface); /// Destructor virtual ~BemGrid(); public: -/* -------------------------------------------------------------------------- */ -/* Actual computations */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Actual computations */ + /* ------------------------------------------------------------------------ */ /// Compute normal vectors to surface void computeSurfaceNormals(); /// Compute influence coefficients void computeInfluence(); /// Compute a Lipschitz constant of gradient void computeInfluenceLipschitz(); /// Apply influence fonctions (p -> u) - void applyInfluenceFunctions(Grid & input, Grid & output); + void applyInfluenceFunctions(Grid& input, Grid& output); /// Apply inverse influence fonctions (u -> p) - void applyInverseInfluenceFunctions(Grid & input, Grid & output); + void applyInverseInfluenceFunctions(Grid& input, + Grid& output); /// Compute true tractions virtual void computeTrueTractions() = 0; /// Compute true displacements virtual void computeTrueDisplacements() = 0; /// Compute equilibrium - virtual void computeEquilibrium(Real tol, const Grid & p_target) = 0; + virtual void computeEquilibrium(Real tol, const Grid& p_target) = 0; /// Compute displacements void computeDisplacementsFromTractions(); /// Compute tractions void computeTractionsFromDisplacements(); /// Compute gaps - void computeGaps(Grid & disp); + void computeGaps(Grid& disp); -/* -------------------------------------------------------------------------- */ -/* Field related computations */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Field related computations */ + /* ------------------------------------------------------------------------ */ /// Project point friction cone - static inline void projectOnFrictionCone(VectorProxy & p, Real mu); + static inline void projectOnFrictionCone(VectorProxy& p, Real mu); /// Project field friction cone - static void projectOnFrictionCone(Grid & field, Real mu); + static void projectOnFrictionCone(Grid& field, Real mu); /// Project on mean value space - static void enforceMeanValue(Grid & field, const Grid & target); + static void enforceMeanValue(Grid& field, + const Grid& target); /// Compute error relative to target mean value - static Real computeMeanValueError(Grid & field, const Grid & target); + static Real computeMeanValueError(Grid& field, + const Grid& target); /// Compute error vector - static void computeMeanValueError(Grid & field, - const Grid & target, - Grid & error_vec); + static void computeMeanValueError(Grid& field, + const Grid& target, + Grid& error_vec); -/* -------------------------------------------------------------------------- */ -/* Getters */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Getters */ + /* ------------------------------------------------------------------------ */ /// Get influence - const GridHermitian2dReal & getInfluence() const {return influence;} + const GridHermitian& getInfluence() const { return influence; } /// Get normals - const Grid2dReal & getSurfaceNormals() const {return surface_normals;} + const Grid& getSurfaceNormals() const { return surface_normals; } /// Get tractions - const Grid2dReal & getTractions() const {return tractions;} + const Grid& getTractions() const { return tractions; } /// Get displacements - const Grid2dReal & getDisplacements() const {return displacements;} + const Grid& getDisplacements() const { return displacements; } /// Get true tractions - const Grid2dReal & getTrueTractions() const; + const Grid& getTrueTractions() const; /// Get true displacements - const Grid2dReal & getTrueDisplacements() const; + const Grid& getTrueDisplacements() const; /// Get gaps - const Grid2dReal & getGaps() const {return gaps;} -/* -------------------------------------------------------------------------- */ -/* Setters */ -/* -------------------------------------------------------------------------- */ + const Grid& getGaps() const { return gaps; } + /* ------------------------------------------------------------------------ */ + /* Setters */ + /* ------------------------------------------------------------------------ */ /// Elasticity parameters - void setElasticity(Real E_, Real nu_) {E = E_; nu = nu_;} + void setElasticity(Real E_, Real nu_) { + E = E_; + nu = nu_; + } /// Friction coefficient - void setMu(Real mu_) {mu = mu_;} + void setMu(Real mu_) { mu = mu_; } /// Max iterations - void setMaxIterations(UInt n) {max_iter = n;} + void setMaxIterations(UInt n) { max_iter = n; } /// Dump frequency - void setDumpFrequency(UInt n) {dump_freq = n;} - + void setDumpFrequency(UInt n) { dump_freq = n; } protected: /// Elasticity constants Real E, nu; /// Friction coefficient Real mu; /// Lipschitz constant of functional gradient Real lipschitz; /// Max iterations UInt max_iter; /// Surface - Surface & surface; + Surface& surface; /// Normal vectors Grid surface_normals; /// Influcence matrices GridHermitian influence; /// Tractions Grid tractions; /// Displacements Grid displacements; /// Gap Grid gaps; /// True tractions - Grid * true_tractions; + Grid* true_tractions; /// True displacements - Grid * true_displacements; + Grid* true_displacements; /// Spectral tractions GridHermitian spectral_tractions; /// Spectral displacements GridHermitian spectral_displacements; /// Dump frequency UInt dump_freq; }; /* -------------------------------------------------------------------------- */ /* Inline definitions */ /* -------------------------------------------------------------------------- */ -inline void BemGrid::projectOnFrictionCone(VectorProxy & p, Real mu) { - Real pt = std::sqrt(p(0)*p(0)+p(1)*p(1)); +inline void BemGrid::projectOnFrictionCone(VectorProxy& p, Real mu) { + Real pt = std::sqrt(p(0) * p(0) + p(1) * p(1)); Real pn = p(2); - Real x = (pn + mu*pt)/(1+mu*mu); + Real x = (pn + mu * pt) / (1 + mu * mu); - if (pt <= mu * pn && pn >= 0) // inside friction cone + if (pt <= mu * pn && pn >= 0) // inside friction cone return; - else if (mu * pt <= std::abs(pn) && pn < 0) // inside "project to origin" cone (undefined normal) - //else if (pn < 0) // project to origin all points with pn < 0 + else if (mu * pt <= std::abs(pn) && + pn < 0) // inside "project to origin" cone (undefined normal) + // else if (pn < 0) // project to origin all points with pn < 0 p = 0; - else { // projectable on cone + else { // projectable on cone p(0) *= mu / pt * x; p(1) *= mu / pt * x; - p(2) = x; + p(2) = x; } } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ -#endif // __BEM_GRID_HH__ +#endif // __BEM_GRID_HH__ diff --git a/src/bem/bem_grid_condat.cpp b/src/bem/bem_grid_condat.cpp index 1bea428..6a3673e 100644 --- a/src/bem/bem_grid_condat.cpp +++ b/src/bem/bem_grid_condat.cpp @@ -1,102 +1,100 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_grid_condat.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -BemGridCondat::BemGridCondat(Surface & surface): - BemGridKato(surface), - grad_step(1.8), - q_step(0.1) -{} +BemGridCondat::BemGridCondat(Surface& surface) + : BemGridKato(surface), grad_step(1.8), q_step(0.1) {} /* -------------------------------------------------------------------------- */ BemGridCondat::~BemGridCondat() {} /* -------------------------------------------------------------------------- */ -void BemGridCondat::updateGradient(Grid &q_vec) { +void BemGridCondat::updateGradient(Grid& q_vec) { Real tmp[3] = {0}; - VectorProxy - q(q_vec.getInternalData(), 3), - q_N(tmp, 3); + VectorProxy q(q_vec.getInternalData(), 3), q_N(tmp, 3); q_N = q; q_N *= q_step; -#pragma omp parallel for - for (auto it = gaps.begin(3) ; it < gaps.end(3) ; ++it) { + //#pragma omp parallel for + for (auto it = gaps.begin(3); it < gaps.end(3); ++it) { VectorProxy g(&(*it), 3); g *= grad_step / lipschitz; g += q; } } /* -------------------------------------------------------------------------- */ -void BemGridCondat::computeEquilibrium(Real tol, const Grid & p_target) { +void BemGridCondat::computeEquilibrium(Real tol, + const Grid& p_target) { this->computeInfluence(); Real f = 0; UInt n_iter = 0; - TAMAAS_ASSERT(p_target.dataSize() == 3, "Applied pressure must have only 3 components"); + TAMAAS_ASSERT(p_target.dataSize() == 3, + "Applied pressure must have only 3 components"); TAMAAS_ASSERT(q_step > 0 && q_step < 1, "q step should be in ]0, 1["); - TAMAAS_ASSERT(grad_step * lipschitz < 2 * (1 - q_step), "grad step * lipschitz should be less than 2 q steps"); + TAMAAS_ASSERT(grad_step * lipschitz < 2 * (1 - q_step), + "grad step * lipschitz should be less than 2 q steps"); this->tractions.uniformSetComponents(p_target); Real q_mem[3] = {0}; Real e_mem[3] = {0}; Real pn_mem[3] = {0}; Real pn1_mem[3] = {0}; Real zero_mem[3] = {0}; - VectorProxy q(q_mem, 3), e(e_mem, 3), pn(pn_mem, 3), pn1(pn1_mem, 3), zero(zero_mem, 3); - Real norm = - p_target(0)*p_target(0) - + p_target(1)*p_target(1) - + p_target(2)*p_target(2); + VectorProxy q(q_mem, 3), e(e_mem, 3), pn(pn_mem, 3), pn1(pn1_mem, 3), + zero(zero_mem, 3); + Real norm = p_target(0) * p_target(0) + p_target(1) * p_target(1) + + p_target(2) * p_target(2); do { computeDisplacementsFromTractions(); computeGaps(displacements); updateGradient(q); beta = computeLambda(); BemGrid::computeMeanValueError(tractions, zero, pn); tractions -= gaps; BemGrid::projectOnFrictionCone(tractions, mu); BemGrid::computeMeanValueError(tractions, zero, pn1); pn1 *= 2; q -= p_target; q += pn1; q -= pn; lambda -= beta; f = computeStoppingCriterion(); printFriendlyMessage(n_iter, f); - } while ((f > tol || e.l2norm() / std::sqrt(norm) > tol) && n_iter++ < this->max_iter); + } while ((f > tol || e.l2norm() / std::sqrt(norm) > tol) && + n_iter++ < this->max_iter); } __END_TAMAAS__ diff --git a/src/bem/bem_grid_condat.hh b/src/bem/bem_grid_condat.hh index 98a2b52..8846146 100644 --- a/src/bem/bem_grid_condat.hh +++ b/src/bem/bem_grid_condat.hh @@ -1,60 +1,60 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_GRID_CONDAT_HH__ #define __BEM_GRID_CONDAT_HH__ /* -------------------------------------------------------------------------- */ #include "bem_grid_kato.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /** * @brief multi component implementation of Condat algorithm * This method's main unknown is the pressure. * Boundary condition is applied mean pressure. */ class BemGridCondat : public BemGridKato { public: /// Constructor - BemGridCondat(Surface & surface); + BemGridCondat(Surface& surface); /// Destructor virtual ~BemGridCondat(); public: -/* -------------------------------------------------------------------------- */ -/* Actual computations */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Actual computations */ + /* ------------------------------------------------------------------------ */ /// Update gradient with a vector - virtual void updateGradient(Grid & q); + virtual void updateGradient(Grid& q); /// Compute equilibrium - virtual void computeEquilibrium(Real tol, const Grid & p_target); + virtual void computeEquilibrium(Real tol, const Grid& p_target); protected: Real grad_step, q_step; }; __END_TAMAAS__ -#endif // __BEM_GRID_CONDAT_HH__ +#endif // __BEM_GRID_CONDAT_HH__ diff --git a/src/bem/bem_grid_kato.cpp b/src/bem/bem_grid_kato.cpp index 773e712..308690a 100644 --- a/src/bem/bem_grid_kato.cpp +++ b/src/bem/bem_grid_kato.cpp @@ -1,211 +1,198 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_grid_kato.hh" #include "surface_statistics.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -BemGridKato::BemGridKato(Surface & surface): - BemGrid(surface), - lambda(surface.size(), surface.getL()), - beta(0) -{ +BemGridKato::BemGridKato(Surface& surface) + : BemGrid(surface), lambda(surface.size(), surface.getL()), beta(0) { this->max_iter = 10000; } /* -------------------------------------------------------------------------- */ -BemGridKato::~BemGridKato() -{} +BemGridKato::~BemGridKato() {} /* -------------------------------------------------------------------------- */ void BemGridKato::computeTrueTractions() { // nothing to do here, tractions are our main unknown } void BemGridKato::computeTrueDisplacements() { // nothing to do here, tractions are our main unknown if (!this->true_displacements) - this->true_displacements = new Grid(this->displacements.sizes(), - this->displacements.getNbComponents()); + this->true_displacements = new Grid( + this->displacements.sizes(), this->displacements.getNbComponents()); *this->true_displacements = this->displacements; const UInt N = this->true_displacements->getNbPoints(); - Real - *d_start = this->true_displacements->getInternalData(), - *g_start = this->gaps.getInternalData(); - VectorProxy - d(nullptr, 3), - g(nullptr, 3); + Real *d_start = this->true_displacements->getInternalData(), + *g_start = this->gaps.getInternalData(); + VectorProxy d(nullptr, 3), g(nullptr, 3); #pragma omp parallel for firstprivate(d, g) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { d.setPointer(d_start + i * d.dataSize()); g.setPointer(g_start + i * g.dataSize()); d(0) = g(0); d(1) = g(1); d(2) = g(2) + this->surface(i) + beta; } } /* -------------------------------------------------------------------------- */ Real BemGridKato::computeFunctional() { Real *p_start = this->tractions.getInternalData(), - *u_start = this->displacements.getInternalData(); + *u_start = this->displacements.getInternalData(); VectorProxy p(nullptr, 3), u(nullptr, 3); Real E = 0; const UInt N = this->tractions.getNbPoints(); -#pragma omp parallel for reduction(+: E) firstprivate(p, u) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp parallel for reduction(+ : E) firstprivate(p, u) + for (UInt i = 0; i < N; i++) { p.setPointer(p_start + i * p.dataSize()); u.setPointer(u_start + i * u.dataSize()); E += 0.5 * p.dot(u) - p(2) * this->surface(i); } return E; } /* -------------------------------------------------------------------------- */ Real BemGridKato::computeLambda() { - Real *g_start = this->gaps.getInternalData(); + Real* g_start = this->gaps.getInternalData(); VectorProxy g(nullptr, 3), g_T(nullptr, 2); const UInt N = this->gaps.getNbPoints(); const UInt nb_components = this->gaps.getNbComponents(); Real beta = std::numeric_limits::max(); // Computing lambda and beta at the same time -#pragma omp parallel for reduction(min: beta) firstprivate(g, g_T) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp parallel for reduction(min : beta) firstprivate(g, g_T) + for (UInt i = 0; i < N; i++) { g.setPointer(g_start + i * nb_components); g_T.setPointer(g_start + i * nb_components); - lambda(i) = g(2) - mu*g_T.l2norm(); - if (lambda(i) < beta) beta = lambda(i); + lambda(i) = g(2) - mu * g_T.l2norm(); + if (lambda(i) < beta) + beta = lambda(i); } return beta; } /* -------------------------------------------------------------------------- */ -void BemGridKato::updateGradient(Grid &q_vec) { - VectorProxy - q(q_vec.getInternalData(), 3), - g(nullptr, 3); +void BemGridKato::updateGradient(Grid& q_vec) { + VectorProxy q(q_vec.getInternalData(), 3), g(nullptr, 3); const UInt N = gaps.getNbPoints(); #pragma omp parallel for firstprivate(g) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { g.setPointer(gaps.getInternalData() + i * g.dataSize()); g += q; } } /* -------------------------------------------------------------------------- */ -void BemGridKato::computeEquilibrium(Real tol, const Grid & g_target) { +void BemGridKato::computeEquilibrium(Real tol, const Grid& g_target) { this->computeInfluence(); Real f = 0; UInt n_iter = 0; - TAMAAS_ASSERT(g_target.dataSize() == 3, "Imposed gap must have only 3 components"); + TAMAAS_ASSERT(g_target.dataSize() == 3, + "Imposed gap must have only 3 components"); - do { + do { this->computeDisplacementsFromTractions(); this->computeGaps(this->displacements); updateGradient(const_cast&>(g_target)); beta = computeLambda(); this->tractions -= this->gaps; BemGrid::projectOnFrictionCone(this->tractions, mu); lambda -= beta; f = computeStoppingCriterion(); printFriendlyMessage(n_iter, f); } while (f > tol && n_iter++ < this->max_iter); } /* -------------------------------------------------------------------------- */ /// Stopping criterion is othogonality between lambda and pressure Real BemGridKato::computeStoppingCriterion() { Real max = std::numeric_limits::min(); Real ortho = 0; Real *p_start = this->tractions.getInternalData(), - *g_start = this->gaps.getInternalData(); + *g_start = this->gaps.getInternalData(); - VectorProxy - p(nullptr, 3), - p_T(nullptr, 2), - g_T(nullptr, 2); + VectorProxy p(nullptr, 3), p_T(nullptr, 2), g_T(nullptr, 2); const UInt N = this->tractions.dataSize() / this->tractions.getNbComponents(); const UInt nb_components = this->tractions.getNbComponents(); const Real hrms = SurfaceStatistics::computeSpectralStdev(this->surface); #pragma omp parallel firstprivate(p, g_T, p_T) { -#pragma omp for reduction(max: max) - for (UInt i = 0 ; i < this->tractions.dataSize() ; i++) { +#pragma omp for reduction(max : max) + for (UInt i = 0; i < this->tractions.dataSize(); i++) { if (max < this->tractions(i)) - max = this->tractions(i); + max = this->tractions(i); } -#pragma omp for reduction(+: ortho) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp for reduction(+ : ortho) + for (UInt i = 0; i < N; i++) { p.setPointer(p_start + i * nb_components); p_T.setPointer(p_start + i * nb_components); g_T.setPointer(g_start + i * nb_components); - ortho += std::abs(p(2)*lambda(i)) - + std::abs((mu*p(2) - p_T.l2norm())*g_T.l2norm()); + ortho += std::abs(p(2) * lambda(i)) + + std::abs((mu * p(2) - p_T.l2norm()) * g_T.l2norm()); } - } // end #pragma omp parallel + } // end #pragma omp parallel return ortho / (max * hrms); } /* -------------------------------------------------------------------------- */ void BemGridKato::printFriendlyMessage(UInt niter, Real conv_crit) { if (niter % this->dump_freq == 0) { UInt prec = std::cout.precision(); - std::cout << niter << " " - << std::scientific << conv_crit << " " - << computeFunctional() << std::endl; + std::cout << niter << " " << std::scientific << conv_crit << " " + << computeFunctional() << std::endl; std::cout << std::fixed; std::cout.precision(prec); } - if (std::isnan(conv_crit)) - std::cerr << "Something went wrong in the solve phase !" << std::endl; + // if (std::isnan(conv_crit)) + // std::cerr << "Something went wrong in the solve phase !" << std::endl; } - - __END_TAMAAS__ diff --git a/src/bem/bem_grid_kato.hh b/src/bem/bem_grid_kato.hh index 1ca47cc..938f4fd 100644 --- a/src/bem/bem_grid_kato.hh +++ b/src/bem/bem_grid_kato.hh @@ -1,84 +1,84 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_GRID_KATO_HH__ #define __BEM_GRID_KATO_HH__ /* -------------------------------------------------------------------------- */ -#include "surface.hh" +#include "bem_grid.hh" #include "grid.hh" +#include "surface.hh" #include "types.hh" -#include "bem_grid.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /** * @brief multi component implementation of Kato algorithm * This method's main unknown is the pressure. * Boundary condition is applied mean gap. */ class BemGridKato : public BemGrid { public: /// Constructor - BemGridKato(Surface & surface); + BemGridKato(Surface& surface); /// Destructor virtual ~BemGridKato(); public: -/* -------------------------------------------------------------------------- */ -/* Actual computations */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Actual computations */ + /* ------------------------------------------------------------------------ */ /// Compute true tractions virtual void computeTrueTractions(); /// Compute true displacements virtual void computeTrueDisplacements(); /// Compute stopping criterion Real computeStoppingCriterion(); /// Compute lambda (Lagrange mult. for p_N >= 0) Real computeLambda(); /// Compute potential energy Real computeFunctional(); /// Update gradient with a vector - virtual void updateGradient(Grid & q); + virtual void updateGradient(Grid& q); /// Compute equilibrium - virtual void computeEquilibrium(Real tol, const Grid & g_target); + virtual void computeEquilibrium(Real tol, const Grid& g_target); -/* -------------------------------------------------------------------------- */ -/* Others */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Others */ + /* ------------------------------------------------------------------------ */ /// Print void printFriendlyMessage(UInt niter, Real conv_crit); /// Get Lambda - const Surface & getLambda() const {return lambda;} + const Surface& getLambda() const { return lambda; } protected: Surface lambda; Real beta; }; __END_TAMAAS__ -#endif // __BEM_GRID_KATO_HH__ +#endif // __BEM_GRID_KATO_HH__ diff --git a/src/bem/bem_grid_polonski.cpp b/src/bem/bem_grid_polonski.cpp index 17779c6..b5d0e4a 100644 --- a/src/bem/bem_grid_polonski.cpp +++ b/src/bem/bem_grid_polonski.cpp @@ -1,276 +1,261 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_grid_polonski.hh" #include "types.hh" -#include #include +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -BemGridPolonski::BemGridPolonski(Surface & surface): - BemGridKato(surface), - search_direction(surface.sizes(), 3), - projected_search_direction(surface.sizes(), 3) -{} +BemGridPolonski::BemGridPolonski(Surface& surface) + : BemGridKato(surface), search_direction(surface.sizes(), 3), + projected_search_direction(surface.sizes(), 3) {} /* -------------------------------------------------------------------------- */ -BemGridPolonski::~BemGridPolonski() -{} +BemGridPolonski::~BemGridPolonski() {} /* -------------------------------------------------------------------------- */ Real BemGridPolonski::computeOptimalStep() { - this->applyInfluenceFunctions(this->search_direction, this->projected_search_direction); + this->applyInfluenceFunctions(this->search_direction, + this->projected_search_direction); centerOnContactArea(this->projected_search_direction); Real num = 0; Real den = 0; const UInt N = search_direction.getNbPoints(); - VectorProxy - p(nullptr, 3), - g(nullptr, 3), - r(nullptr, 3), - t(nullptr, 3); + VectorProxy p(nullptr, 3), g(nullptr, 3), r(nullptr, 3), t(nullptr, 3); UInt nc = search_direction.getNbComponents(); -#pragma omp parallel for reduction(+:num, den) firstprivate(p, g, r, t) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp parallel for reduction(+ : num, den) firstprivate(p, g, r, t) + for (UInt i = 0; i < N; i++) { p.setPointer(this->tractions.getInternalData() + i * nc); g.setPointer(this->gaps.getInternalData() + i * nc); r.setPointer(this->projected_search_direction.getInternalData() + i * nc); t.setPointer(this->search_direction.getInternalData() + i * nc); if (p(2) > 0) { num += g.dot(t); den += r.dot(t); } } Real tau = num / den; return tau; } /* -------------------------------------------------------------------------- */ void BemGridPolonski::updateSearchDirection(Real delta, Real G, Real G_old) { - Real * t_start = search_direction.getInternalData(), - * g_start = this->gaps.getInternalData(), - * p_start = this->tractions.getInternalData(); + Real *t_start = search_direction.getInternalData(), + *g_start = this->gaps.getInternalData(), + *p_start = this->tractions.getInternalData(); - VectorProxy - t(nullptr, 3), - p(nullptr, 3), - g(nullptr, 3); + VectorProxy t(nullptr, 3), p(nullptr, 3), g(nullptr, 3); UInt nb_components = 3; const UInt N = search_direction.getNbPoints(); #pragma omp parallel for firstprivate(t, p, g) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { t.setPointer(t_start + i * nb_components); g.setPointer(g_start + i * nb_components); p.setPointer(p_start + i * nb_components); if (p(2) > 0) { t *= delta * G / G_old; t += g; } else { t = 0; } } } - /* -------------------------------------------------------------------------- */ Real BemGridPolonski::computeGradientNorm() { Real G = 0; - VectorProxy - g(nullptr, 3), - p(nullptr, 3); + VectorProxy g(nullptr, 3), p(nullptr, 3); const UInt N = this->gaps.getNbPoints(); -#pragma omp parallel for reduction(+:G) firstprivate(g, p) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp parallel for reduction(+ : G) firstprivate(g, p) + for (UInt i = 0; i < N; i++) { g.setPointer(this->gaps.getInternalData() + i * g.dataSize()); p.setPointer(this->tractions.getInternalData() + i * p.dataSize()); if (p(2) > 0) G += g.dot(g); } return G; } /* -------------------------------------------------------------------------- */ -void BemGridPolonski::centerOnContactArea(Grid &field) { +void BemGridPolonski::centerOnContactArea(Grid& field) { // Compute average values on contact Real f0 = 0, f1 = 0, f2 = 0; - Real *f = field.getInternalData(), *p_start = this->tractions.getInternalData(); + Real *f = field.getInternalData(), + *p_start = this->tractions.getInternalData(); VectorProxy v(nullptr, 3); VectorProxy p(nullptr, 3); const UInt N = field.getNbPoints(); UInt nb_contact = 0; #pragma omp parallel firstprivate(v, p) { -#pragma omp for reduction(+:f0, f1, f2, nb_contact) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp for reduction(+ : f0, f1, f2, nb_contact) + for (UInt i = 0; i < N; i++) { v.setPointer(f + i * v.dataSize()); p.setPointer(p_start + i * p.dataSize()); if (p(2) > 0) { - f0 += v(0); - f1 += v(1); - f2 += v(2); - nb_contact++; + f0 += v(0); + f1 += v(1); + f2 += v(2); + nb_contact++; } } #pragma omp single { - f0 /= nb_contact; f1 /= nb_contact; f2 /= nb_contact; + f0 /= nb_contact; + f1 /= nb_contact; + f2 /= nb_contact; } #pragma omp barrier #pragma omp for - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { v.setPointer(f + i * v.dataSize()); v(0) -= f0; v(1) -= f1; v(2) -= f2; } - } // end #pragma omp parallel + } // end #pragma omp parallel } /* -------------------------------------------------------------------------- */ Real BemGridPolonski::updateTractions(Real alpha) { - Real - *p_start = this->tractions.getInternalData(), - *g_start = this->gaps.getInternalData(), - *t_start = search_direction.getInternalData(); - VectorProxy - p(nullptr, 3), - g(nullptr, 3), - t(nullptr, 3); + Real *p_start = this->tractions.getInternalData(), + *g_start = this->gaps.getInternalData(), + *t_start = search_direction.getInternalData(); + VectorProxy p(nullptr, 3), g(nullptr, 3), t(nullptr, 3); const UInt N = this->tractions.getNbPoints(); const UInt nb_components = this->tractions.getNbComponents(); UInt nb_iol = 0; #pragma omp parallel firstprivate(p, g, t) { Real alpha_t_data[3] = {0}; VectorProxy alpha_t(alpha_t_data, 3); -#pragma omp for reduction(+:nb_iol) - for (UInt i = 0 ; i < N ; i++) { +#pragma omp for reduction(+ : nb_iol) + for (UInt i = 0; i < N; i++) { p.setPointer(p_start + i * nb_components); g.setPointer(g_start + i * nb_components); t.setPointer(t_start + i * nb_components); if (p(2) > 0) { - alpha_t = t; - alpha_t *= alpha; - p -= alpha_t; - BemGrid::projectOnFrictionCone(p, mu); + alpha_t = t; + alpha_t *= alpha; + p -= alpha_t; + BemGrid::projectOnFrictionCone(p, mu); } if (p(2) == 0 && lambda(i) < 0) { - nb_iol++; - p(2) -= alpha * lambda(i); + nb_iol++; + p(2) -= alpha * lambda(i); } } - } // end #pragma omp parallel + } // end #pragma omp parallel return (Real) !(nb_iol > 0); } /* -------------------------------------------------------------------------- */ /// p_target is just a 3 component single value vector ! -void BemGridPolonski::computeEquilibrium(Real tol, const Grid & p_target) { +void BemGridPolonski::computeEquilibrium(Real tol, + const Grid& p_target) { this->computeInfluence(); Real f = 0; UInt n_iter = 0; - TAMAAS_ASSERT(p_target.dataSize() == 3, "Applied pressure must have only 3 components"); + TAMAAS_ASSERT(p_target.dataSize() == 3, + "Applied pressure must have only 3 components"); - Real - delta = 0, - G = 0, - G_old = 1, - tau = 0; + Real delta = 0, G = 0, G_old = 1, tau = 0; setPressure(p_target); // main loop do { this->computeDisplacementsFromTractions(); this->computeGaps(this->displacements); centerOnContactArea(this->gaps); - beta = computeLambda(); // note: beta is member variable + beta = computeLambda(); // note: beta is member variable G = computeGradientNorm(); // if (G == 0) break; updateSearchDirection(delta, G, G_old); G_old = G; tau = computeOptimalStep(); delta = updateTractions(tau); - //Real f_ = 0; - //do { + // Real f_ = 0; + // do { // enforcePressureBalance(p_target); // enforcePressureConstraints(); // f_ = computeEquilibriumError(p_target); //} while (f_ > 1e-6); lambda -= beta; f = computeStoppingCriterion(); printFriendlyMessage(n_iter, f); } while (f > tol && n_iter++ < this->max_iter); } /* -------------------------------------------------------------------------- */ -void BemGridPolonski::setPressure(const Grid & p_target) { +void BemGridPolonski::setPressure(const Grid& p_target) { VectorProxy p(nullptr, 3); const UInt N = this->tractions.getNbPoints(); - Real *p_start = this->tractions.getInternalData(); + Real* p_start = this->tractions.getInternalData(); #pragma omp parallel for firstprivate(p) - for (UInt i = 0 ; i < N ; i++) { + for (UInt i = 0; i < N; i++) { p.setPointer(p_start + i * p.dataSize()); p = p_target; } } __END_TAMAAS__ diff --git a/src/bem/bem_grid_polonski.hh b/src/bem/bem_grid_polonski.hh index 158b2c5..c5ca6c2 100644 --- a/src/bem/bem_grid_polonski.hh +++ b/src/bem/bem_grid_polonski.hh @@ -1,78 +1,80 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_GRID_POLONSKI_HH__ #define __BEM_GRID_POLONSKI_HH__ /* -------------------------------------------------------------------------- */ -#include "surface.hh" +#include "bem_grid_kato.hh" #include "grid.hh" +#include "surface.hh" #include "types.hh" -#include "bem_grid_kato.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ // typedef for swig typedef Grid Grid1dReal; /** * @brief multi component implementation of Polonski algorithm * This method's main unknown is the pressure. */ class BemGridPolonski : public BemGridKato { public: /// Constructor - BemGridPolonski(Surface & surface); + BemGridPolonski(Surface& surface); /// Destructor virtual ~BemGridPolonski(); public: -/* -------------------------------------------------------------------------- */ -/* Actual computations */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- + */ + /* Actual computations */ + /* -------------------------------------------------------------------------- + */ /// Compute equilibrium - virtual void computeEquilibrium(Real tol, const Grid & p_target); + virtual void computeEquilibrium(Real tol, const Grid& p_target); /// Compute gap functional Real computeGradientNorm(); /// Compute optimal step size Real computeOptimalStep(); /// Center field on contact area - void centerOnContactArea(Grid & field); + void centerOnContactArea(Grid& field); /// Update search direction void updateSearchDirection(Real delta, Real G, Real G_old); /// Update tractions Real updateTractions(Real tau); /// Set pressure on all points - void setPressure(const Grid & p_target); + void setPressure(const Grid& p_target); protected: Grid search_direction; Grid projected_search_direction; }; __END_TAMAAS__ -#endif // __BEM_GRID_POLONSKI_HH__ +#endif // __BEM_GRID_POLONSKI_HH__ diff --git a/src/bem/bem_grid_teboulle.cpp b/src/bem/bem_grid_teboulle.cpp index fed56a0..9e532f9 100644 --- a/src/bem/bem_grid_teboulle.cpp +++ b/src/bem/bem_grid_teboulle.cpp @@ -1,85 +1,83 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_grid_teboulle.hh" #include "surface_statistics.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -BemGridTeboulle::BemGridTeboulle(Surface & s): - BemGridKato(s), - z(s.sizes(), 3), - tractions_old(s.sizes(), 3) -{} +BemGridTeboulle::BemGridTeboulle(Surface& s) + : BemGridKato(s), z(s.sizes(), 3), tractions_old(s.sizes(), 3) {} /* -------------------------------------------------------------------------- */ -BemGridTeboulle::~BemGridTeboulle() -{} +BemGridTeboulle::~BemGridTeboulle() {} /* -------------------------------------------------------------------------- */ -void BemGridTeboulle::computeEquilibrium(Real tol, const Grid & g_target) { +void BemGridTeboulle::computeEquilibrium(Real tol, + const Grid& g_target) { this->computeInfluence(); Real f = 0, l = 0; Real t[2] = {1, 1}; UInt n_iter = 0; - TAMAAS_ASSERT(g_target.dataSize() == 3, "Applied pressure must have only 3 components"); + TAMAAS_ASSERT(g_target.dataSize() == 3, + "Applied pressure must have only 3 components"); // Real surface_mean = SurfaceStatistics::computeAverage(this->surface, 0); // this->surface -= (surface_mean + g_target(2)); - do { + do { applyInfluenceFunctions(z, displacements); computeGaps(displacements); updateGradient(const_cast&>(g_target)); beta = computeLambda(); gaps /= lipschitz; z -= gaps; BemGrid::projectOnFrictionCone(z, mu); tractions = z; - t[1] = (1. + std::sqrt(4*t[0]*t[0] + 1)) / 2.; - l = 1 + (t[0]-1)/t[1]; + t[1] = (1. + std::sqrt(4 * t[0] * t[0] + 1)) / 2.; + l = 1 + (t[0] - 1) / t[1]; z -= tractions_old; z *= l; z += tractions_old; t[0] = t[1]; tractions_old = tractions; lambda -= beta; f = computeStoppingCriterion(); printFriendlyMessage(n_iter, f); } while (f > tol && n_iter++ < this->max_iter); gaps *= lipschitz; - //computeDisplacementsFromTractions(); - //computeGaps(displacements); + // computeDisplacementsFromTractions(); + // computeGaps(displacements); } __END_TAMAAS__ diff --git a/src/bem/bem_grid_teboulle.hh b/src/bem/bem_grid_teboulle.hh index 67a9e46..b198d3e 100644 --- a/src/bem/bem_grid_teboulle.hh +++ b/src/bem/bem_grid_teboulle.hh @@ -1,63 +1,65 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_GRID_TEBOULLE_HH__ #define __BEM_GRID_TEBOULLE_HH__ /* -------------------------------------------------------------------------- */ -#include "surface.hh" +#include "bem_grid_kato.hh" #include "grid.hh" +#include "surface.hh" #include "types.hh" -#include "bem_grid_kato.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /** * @brief multi component implementation of Beck-Teboulle algorithm * This method's main unknown is the pressure. */ class BemGridTeboulle : public BemGridKato { public: /// Constructor - BemGridTeboulle(Surface & surface); + BemGridTeboulle(Surface& surface); /// Destructor virtual ~BemGridTeboulle(); public: -/* -------------------------------------------------------------------------- */ -/* Actual computations */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- + */ + /* Actual computations */ + /* -------------------------------------------------------------------------- + */ /// Compute equilibrium - virtual void computeEquilibrium(Real tol, const Grid & p_target); + virtual void computeEquilibrium(Real tol, const Grid& p_target); protected: Grid z; Grid tractions_old; }; __END_TAMAAS__ -#endif // __BEM_GRID_TEBOULLE_HH__ +#endif // __BEM_GRID_TEBOULLE_HH__ diff --git a/src/bem/bem_interface.hh b/src/bem/bem_interface.hh index 215b89f..97cd7a0 100644 --- a/src/bem/bem_interface.hh +++ b/src/bem/bem_interface.hh @@ -1,105 +1,99 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_INTERFACE_H #define BEM_INTERFACE_H -#include "surface.hh" -#include "fftransform.hh" #include "fft_plan_manager.hh" +#include "fftransform.hh" +#include "surface.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ - - class BemInterface { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemInterface(Surface & surface): - surface(surface), - spectral_surface(surface.size(),surface.getL()) { + BemInterface(Surface& surface) + : surface(surface), spectral_surface(surface.size(), surface.getL()) { this->computeSpectralSurface(); }; virtual ~BemInterface(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: - //! compute the displacements from the tractions - virtual void computeDisplacementsFromTractions(){SURFACE_FATAL("TO BE IMPLEMENTED")}; + virtual void computeDisplacementsFromTractions(){ + SURFACE_FATAL("TO BE IMPLEMENTED")}; //! compute the tractions from the displacements - virtual void computeTractionsFromDisplacements(){SURFACE_FATAL("TO BE IMPLEMENTED")}; + virtual void computeTractionsFromDisplacements(){ + SURFACE_FATAL("TO BE IMPLEMENTED")}; public: - //! compute the spectral surface - virtual void computeSpectralSurface(){ - FFTransform & plan = FFTPlanManager::get().createPlan(surface, spectral_surface); + virtual void computeSpectralSurface() { + FFTransform& plan = + FFTPlanManager::get().createPlan(surface, spectral_surface); plan.forwardTransform(); }; - /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! return the actual tractions - virtual const Surface & getTractions() const = 0; + virtual const Surface& getTractions() const = 0; //! return the actual displacements - virtual const Surface & getDisplacements() const = 0; + virtual const Surface& getDisplacements() const = 0; //! return the manipulated surface - const Surface & getSurface() const{return this->surface;}; + const Surface& getSurface() const { return this->surface; }; //! return the manipulated surface in fourier space - const SurfaceComplex & getSpectralSurface() const{return this->spectral_surface;}; + const SurfaceComplex& getSpectralSurface() const { + return this->spectral_surface; + }; //! return the manipulated surface - void setSurface(Surface & surface){this->surface = surface;}; - + void setSurface(Surface& surface) { this->surface = surface; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! the surface profile we work with - Surface & surface; + Surface& surface; //! the surface profile in fourier space SurfaceComplex spectral_surface; - }; __END_TAMAAS__ #endif /* BEM_INTERFACE_H */ diff --git a/src/bem/bem_kato.cpp b/src/bem/bem_kato.cpp index 1d00b90..82c9eb8 100644 --- a/src/bem/bem_kato.cpp +++ b/src/bem/bem_kato.cpp @@ -1,300 +1,267 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include -#include "surface.hh" #include "bem_kato.hh" -#include -#include +#include "surface.hh" #include #include +#include #include -#include -/* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ - -Real BemKato::linescan(Real scale,Real pressure){ +Real BemKato::linescan(Real scale, Real pressure) { updatePressure(scale); shiftPressure(pressure); truncatePressure(); Real res = computeF(); return res; } /* -------------------------------------------------------------------------- */ - -Real BemKato::linesearch(Real & hmax, Real fold, - Real pressure, int search_flag){ - if (search_flag){ - Real h = hmax; +Real BemKato::linesearch(Real& hmax, Real fold, Real pressure, + int search_flag) { + if (search_flag) { + Real h = hmax; // Real fold = bem.computeF(); - //if (fold == 0) fold = 1e300; - Real f = linescan(h,pressure); - if (f < fold) return f; + // if (fold == 0) fold = 1e300; + Real f = linescan(h, pressure); + if (f < fold) + return f; - while (f > fold){ + while (f > fold) { h *= 0.5; - if (h < 1e-3) throw 1; - f = linescan(h,pressure); + if (h < 1e-3) + throw 1; + f = linescan(h, pressure); } - f = linescan(h,pressure); + f = linescan(h, pressure); // if (hmax / h > 10) hmax /=2; return f; } - return linescan(hmax,pressure); + return linescan(hmax, pressure); } /* -------------------------------------------------------------------------- */ - -Real BemKato::computeEquilibrium(Real epsilon, - Real pressure){ +Real BemKato::computeEquilibrium(Real epsilon, Real pressure) { // UInt n = surface.size(); // UInt size = n*n; this->computeSpectralInfluenceOverDisplacement(); this->computeDisplacementsFromTractions(); this->functional->computeGradFP(); this->backupTractions(); Real f = 1.; Real fPrevious = 1e300; this->nb_iterations = 0; this->convergence_iterations.clear(); - while(f > epsilon && this->nb_iterations < this->max_iterations) { + while (f > epsilon && this->nb_iterations < this->max_iterations) { fPrevious = f; this->computeDisplacementsFromTractions(); this->functional->computeGradFP(); this->backupTractions(); try { - f = linescan(1.,pressure); - } - catch (int e){ + f = linescan(1., pressure); + } catch (int e) { std::cout << " line search failed " << std::endl; - f = linescan(1,pressure); + f = linescan(1, pressure); nb_iterations = 0; break; } if (nb_iterations % dump_freq == 0) { - // std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << f-fold << " " << ((f-fold)/forigin) << std::endl; - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f << " " << f-fPrevious - << std::endl; + // std::cout << std::scientific << std::setprecision(10) << + // nb_iterations << " " << f << " " << f-fold << " " << + // ((f-fold)/forigin) << std::endl; + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f << " " << f - fPrevious << std::endl; } convergence_iterations.push_back(f); ++nb_iterations; } - this->computeTrueDisplacements(); this->computeGaps(); - - return f; } /* -------------------------------------------------------------------------- */ - -void BemKato::updatePressure(Real scale){ - STARTTIMER("updatePressure"); +void BemKato::updatePressure(Real scale) { UInt n = surface.size(); - UInt size = n*n; - const Surface & gradF = this->functional->getGradF(); + UInt size = n * n; + const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->surface_tractions(i) = - this->surface_tractions_backup(i) - gradF(i) * scale; + this->surface_tractions_backup(i) - gradF(i) * scale; } - STOPTIMER("updatePressure"); } /* -------------------------------------------------------------------------- */ -void BemKato::backupTractions(){ - STARTTIMER("switchPressure"); - +void BemKato::backupTractions() { UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->surface_tractions_backup(i) = this->surface_tractions(i); } - - STOPTIMER("switchPressure"); } - /* -------------------------------------------------------------------------- */ -Real BemKato::positivePressure(Real step){ - STARTTIMER("positivePressure"); - +Real BemKato::positivePressure(Real step) { UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; Real p_tot = 0.0; -#pragma omp parallel for reduction(+:p_tot) +#pragma omp parallel for reduction(+ : p_tot) for (UInt i = 0; i < size; ++i) { Real sh_press = this->surface_tractions(i) + step; - if (sh_press > max_pressure) p_tot += max_pressure; - else p_tot += sh_press*(sh_press > 0); + if (sh_press > max_pressure) + p_tot += max_pressure; + else + p_tot += sh_press * (sh_press > 0); } - STOPTIMER("positivePressure"); - return p_tot/n/n; + return p_tot / n / n; } /* -------------------------------------------------------------------------- */ - -void BemKato::shiftPressure(Real required_pressure){ +void BemKato::shiftPressure(Real required_pressure) { Real step_min = -10; - Real step_max = 10; - - STARTTIMER("shiftPressureInitialGuess"); + Real step_max = 10; Real p_max = positivePressure(step_max); Real p_min = positivePressure(step_min); - - for(UInt i = 0; p_max < required_pressure && i < 8; ++i, step_max*=10) { + for (UInt i = 0; p_max < required_pressure && i < 8; ++i, step_max *= 10) { p_max = positivePressure(step_max); } - for(UInt i = 0; p_min > required_pressure && i < 8; ++i, step_min*=10) { + for (UInt i = 0; p_min > required_pressure && i < 8; ++i, step_min *= 10) { p_min = positivePressure(step_min); } Real p = positivePressure(0.0); Real epsilon = 1e-12; - STOPTIMER("shiftPressureInitialGuess"); - - STARTTIMER("shiftPressureDichotomy"); - while (fabs(step_min - step_max) > epsilon){ - Real step = (step_min + step_max)/2; + while (fabs(step_min - step_max) > epsilon) { + Real step = (step_min + step_max) / 2; p = positivePressure(step); - if (p > required_pressure) step_max = step; - else if (p < required_pressure) step_min = step; + if (p > required_pressure) + step_max = step; + else if (p < required_pressure) + step_min = step; else { step_max = step; step_min = step; } } - STOPTIMER("shiftPressureDichotomy"); - STARTTIMER("shiftPressureTrueShift"); UInt n = surface.size(); - UInt size = n*n; - //shift the pressure so that satisfies the constraint + UInt size = n * n; + // shift the pressure so that satisfies the constraint #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->surface_tractions(i) += (step_max+step_min)/2; + this->surface_tractions(i) += (step_max + step_min) / 2; } - STOPTIMER("shiftPressureTrueShift"); } /* -------------------------------------------------------------------------- */ -void BemKato::truncatePressure(){ - STARTTIMER("truncatePressure"); - +void BemKato::truncatePressure() { UInt n = surface.size(); - UInt size = n*n; - //shift the pressure so that satisfies the constraint + UInt size = n * n; + // shift the pressure so that satisfies the constraint #pragma omp parallel for for (UInt i = 0; i < size; ++i) { if (this->surface_tractions(i) > max_pressure) this->surface_tractions(i) = max_pressure; - else this->surface_tractions(i) *= (this->surface_tractions(i) > 0); + else + this->surface_tractions(i) *= (this->surface_tractions(i) > 0); } - - STOPTIMER("truncatePressure"); } /* -------------------------------------------------------------------------- */ - - void BemKato::computeTrueDisplacements() { UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; Real shift = 1e300; -#pragma omp parallel for reduction(min: shift) - for (UInt i = 0 ; i < size ; i++) { +#pragma omp parallel for reduction(min : shift) + for (UInt i = 0; i < size; i++) { if (surface_displacements(i) - shift - surface(i) < 0. && - surface_tractions(i) < max_pressure){ + surface_tractions(i) < max_pressure) { shift = surface_displacements(i) - surface(i); } } this->true_displacements = surface_displacements; this->true_displacements -= shift; } /* -------------------------------------------------------------------------- */ Real BemKato::computeF() { UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; Real res = 0; Real t_sum = std::abs(SurfaceStatistics::computeSum(surface_tractions)); computeTrueDisplacements(); -#pragma omp parallel for reduction(+:res) +#pragma omp parallel for reduction(+ : res) for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) == this->max_pressure) continue; - res += std::abs(surface_tractions(i) * ( this->true_displacements(i)-surface(i))); + if (this->surface_tractions(i) == this->max_pressure) + continue; + res += std::abs(surface_tractions(i) * + (this->true_displacements(i) - surface(i))); // res += // this->surface_tractions[i].real() // *(surface_displacements[i].real() - surface[i].real()); } - return res/std::abs(t_sum); - + return res / std::abs(t_sum); } /* -------------------------------------------------------------------------- */ - __END_TAMAAS__ diff --git a/src/bem/bem_kato.hh b/src/bem/bem_kato.hh index 3472d96..ec815d2 100644 --- a/src/bem/bem_kato.hh +++ b/src/bem/bem_kato.hh @@ -1,112 +1,103 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_KATO_H #define BEM_KATO_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" -#include "elastic_energy_functional.hh" #include "complimentary_term_functional.hh" +#include "elastic_energy_functional.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemKato : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemKato(Surface & p) : - BemFFTBase(p), - surface_tractions_backup(p.size(),p.getL()){ + BemKato(Surface& p) + : BemFFTBase(p), surface_tractions_backup(p.size(), p.getL()) { e_star = 1.; max_pressure = 1e300; this->functional->addFunctionalTerm(new ComplimentaryTermFunctional(*this)); }; virtual ~BemKato(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: - - //! compute the equilibrium situation - Real computeEquilibrium(Real epsilon,Real pressure); + Real computeEquilibrium(Real epsilon, Real pressure); public: - //! perform a line scan in a given direction - Real linescan(Real scale,Real pressure); + Real linescan(Real scale, Real pressure); //! perform a line search - Real linesearch(Real & hmax, Real fold, - Real pressure, int search_flag); + Real linesearch(Real& hmax, Real fold, Real pressure, int search_flag); //! make a step in the gradient direction(copy in pressure2) void updatePressure(Real scale); //! backup tractions before doing the linescan void backupTractions(); //! find the constant pressure shift making balance with load void shiftPressure(Real required_pressure); //! truncate the pressure to positive values Real positivePressure(Real step); //! compute the reaction (sum positive pressures) void truncatePressure(); //! compute true displacements void computeTrueDisplacements(); //! compute convergence criterion Real computeF(); - /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! get the number of iterations - UInt getNbIterations() const{return this->nb_iterations;}; + UInt getNbIterations() const { return this->nb_iterations; }; //! get the convergence steps of iterations - const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + const std::vector& getConvergenceIterations() const { + return this->convergence_iterations; + }; //! set the maximal pressure admissible - void setMaxPressure(Real max_pressure){this->max_pressure = max_pressure;}; + void setMaxPressure(Real max_pressure) { this->max_pressure = max_pressure; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! surface of tractions used during steepest descent Surface surface_tractions_backup; //! maximal pressure admissible (for perfectly plastic purpose) Real max_pressure; - }; - __END_TAMAAS__ #endif /* BEM_KATO_H */ diff --git a/src/bem/bem_meta_functional.cpp b/src/bem/bem_meta_functional.cpp index 2e54ea4..db16025 100644 --- a/src/bem/bem_meta_functional.cpp +++ b/src/bem/bem_meta_functional.cpp @@ -1,95 +1,95 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the - * functionals of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. + * functionals of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "bem_meta_functional.hh" #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -MetaFunctional::MetaFunctional(BemFFTBase & bem): - Functional(bem) { +MetaFunctional::MetaFunctional(BemFFTBase& bem) : Functional(bem) { this->gradF = new Surface(this->bem.getSurface().size(), - this->bem.getSurface().getL()); + this->bem.getSurface().getL()); } /* -------------------------------------------------------------------------- */ MetaFunctional::~MetaFunctional() { auto it = functionals.begin(); auto end = functionals.end(); - for (; it != end ; ++it) delete *it; + for (; it != end; ++it) + delete *it; delete this->gradF; } /* -------------------------------------------------------------------------- */ Real MetaFunctional::computeF() { Real F = 0; auto it = functionals.begin(); auto end = functionals.end(); - for (; it != end ; ++it) { + for (; it != end; ++it) { F += (*it)->computeF(); } return F; } /* -------------------------------------------------------------------------- */ void MetaFunctional::computeGradFP() { bem.computeDisplacementsFromTractions(); *this->gradF = 0; auto it = functionals.begin(); auto end = functionals.end(); - for (; it != end ; ++it) { + for (; it != end; ++it) { (*it)->computeGradFP(); } } /* -------------------------------------------------------------------------- */ void MetaFunctional::computeGradFU() { bem.computeTractionsFromDisplacements(); *this->gradF = 0; auto it = functionals.begin(); auto end = functionals.end(); - for (; it != end ; ++it) { + for (; it != end; ++it) { (*it)->computeGradFU(); } } /* -------------------------------------------------------------------------- */ void MetaFunctional::addFunctionalTerm(Functional* term) { functionals.push_back(term); term->setGradFPointer(this->gradF); this->copyParameters(term->getParametersMap()); } __END_TAMAAS__ diff --git a/src/bem/bem_meta_functional.hh b/src/bem/bem_meta_functional.hh index 659b354..1a18c89 100644 --- a/src/bem/bem_meta_functional.hh +++ b/src/bem/bem_meta_functional.hh @@ -1,59 +1,59 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __BEM_META_FUNCTIONAL_HH__ #define __BEM_META_FUNCTIONAL_HH__ #include "bem_functional.hh" #include "tamaas.hh" #include __BEGIN_TAMAAS__ /// Meta functional that contains list of functionals class MetaFunctional : public Functional { public: /// Constructor - explicit MetaFunctional(BemFFTBase & bem); - + explicit MetaFunctional(BemFFTBase& bem); + /// Destructor virtual ~MetaFunctional(); public: Real computeF(); void computeGradFU(); void computeGradFP(); - void addFunctionalTerm(Functional * term); + void addFunctionalTerm(Functional* term); protected: - std::list functionals; + std::list functionals; }; __END_TAMAAS__ -#endif // __BEM_META_FUNCTIONAL_HH__ +#endif // __BEM_META_FUNCTIONAL_HH__ diff --git a/src/bem/bem_penalty.cpp b/src/bem/bem_penalty.cpp index 8682b20..a21f133 100644 --- a/src/bem/bem_penalty.cpp +++ b/src/bem/bem_penalty.cpp @@ -1,255 +1,200 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include -#include "surface.hh" #include "bem_penalty.hh" -#include -#include +#include "surface.hh" #include #include +#include #include -#include -/* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ void BemPenalty::computeTractionsFromDisplacements() { - this->applyInverseInfluenceFunctions(this->true_displacements,this->surface_tractions); + this->applyInverseInfluenceFunctions(this->true_displacements, + this->surface_tractions); } - -Real BemPenalty::computeEquilibrium(Real epsilon, - Real mean_displacement, Real penalization_parameter) { +Real BemPenalty::computeEquilibrium(Real epsilon, Real mean_displacement, + Real penalization_parameter) { this->computeSpectralInfluenceOverDisplacement(); - this->search_direction = 0.; - this->true_displacements =0; - this->true_displacements = mean_displacement; - this->computeGaps(); -std::ofstream file ("output.txt"); - - Real f = 1e300; + this->search_direction = 0.; + this->true_displacements = 0; + this->true_displacements = mean_displacement; + this->computeGaps(); + std::ofstream file("output.txt"); - std::cout << "moyenne deplacement "<< SurfaceStatistics::computeAverage(this->true_displacements, 0)<< std::endl; + Real f = 1e300; - convergence_iterations.clear(); - nb_iterations = 0; - - max_iterations =5000; - - - - while (f> epsilon && nb_iterations++ < max_iterations) { - - this->functional->computeGradFU(); - - this->computeSearchDirection(mean_displacement,penalization_parameter); - - Real alpha=0.001; - - this->old_displacements=this->true_displacements; + std::cout << "moyenne deplacement " + << SurfaceStatistics::computeAverage(this->true_displacements, 0) + << std::endl; + convergence_iterations.clear(); + nb_iterations = 0; + max_iterations = 5000; + while (f > epsilon && nb_iterations++ < max_iterations) { + this->functional->computeGradFU(); - this->updateUnknown( alpha, mean_displacement); + this->computeSearchDirection(mean_displacement, penalization_parameter); + Real alpha = 0.001; - this->computeGaps(); + this->old_displacements = this->true_displacements; + this->updateUnknown(alpha, mean_displacement); + this->computeGaps(); - f = computeStoppingCriterion(); + f = computeStoppingCriterion(); if (nb_iterations % dump_freq == 0) { - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f << std::fixed << std::endl; - + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f << std::fixed << std::endl; this->computePressures(mean_displacement); - Real orth=0.; - UInt n = surface.size(); - UInt size = n*n; - - #pragma omp parallel for reduction(+:orth) - for (UInt i = 0; i < size; ++i) { - - orth += std::abs(surface_tractions(i) * ( this->true_displacements(i)-surface(i))); - - } - - - - file<< std::scientific << std::setprecision(10)<< nb_iterations << " " - <true_displacements(i) - surface(i))); + } + file << std::scientific << std::setprecision(10) << nb_iterations << " " + << f << " " << orth << std::endl; } convergence_iterations.push_back(f); } - - this->computePressures(mean_displacement); + this->computePressures(mean_displacement); file.close(); return f; } /* -------------------------------------------------------------------------- */ Real BemPenalty::computeStoppingCriterion() { + Real crit = 0.; + Real disp_norm = 0.; - Real crit=0.; - Real disp_norm = 0.; - - UInt n = surface.size(); - UInt size = n*n; - - #pragma omp parallel for reduction(+:crit, disp_norm) - for (UInt i = 0; i < size; ++i) { - - - crit += this->search_direction(i)*this->search_direction(i); - disp_norm += (true_displacements(i)*true_displacements(i)); - } + UInt n = surface.size(); + UInt size = n * n; +#pragma omp parallel for reduction(+ : crit, disp_norm) + for (UInt i = 0; i < size; ++i) { + crit += this->search_direction(i) * this->search_direction(i); + disp_norm += (true_displacements(i) * true_displacements(i)); + } - return crit / disp_norm; + return crit / disp_norm; } /* -------------------------------------------------------------------------- */ -void BemPenalty::computeSearchDirection(Real mean_displacement,Real penalization_parameter) { - STARTTIMER("computeOptimalStep"); - - +void BemPenalty::computeSearchDirection(Real mean_displacement, + Real penalization_parameter) { UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 1; i < size; ++i) { - this->search_direction(i)=gradF(i); - - - - if (gap(i)<0) - { - this->search_direction(i)+=penalization_parameter*gap(i); - - - - } -} - - + this->search_direction(i) = gradF(i); + if (gap(i) < 0) { + this->search_direction(i) += penalization_parameter * gap(i); + } + } } /* -------------------------------------------------------------------------- */ Real BemPenalty::computeOptimalStep() { - STARTTIMER("computeOptimalStep"); - this->applyInverseInfluenceFunctions(search_direction, surface_r); UInt n = surface.size(); - UInt size = n*n; - Real numerator = 0., denominator = 0.; - -#pragma omp parallel for reduction(+: numerator, denominator) - for (UInt i = 0; i < size; ++i) { - numerator += search_direction(i) * search_direction(i); - denominator += surface_r(i) * search_direction(i); - } - - Real alpha = numerator / denominator; - - STOPTIMER("computeOptimalStep"); - return alpha; + UInt size = n * n; + Real numerator = 0., denominator = 0.; +#pragma omp parallel for reduction(+ : numerator, denominator) + for (UInt i = 0; i < size; ++i) { + numerator += search_direction(i) * search_direction(i); + denominator += surface_r(i) * search_direction(i); + } + Real alpha = numerator / denominator; + return alpha; } - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void BemPenalty::updateUnknown(Real alpha, Real mean_displacement) { - STARTTIMER("updateDisplacements"); - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) -= alpha*this->search_direction(i); - + this->true_displacements(i) -= alpha * this->search_direction(i); } -Real moyenne=SurfaceStatistics::computeAverage(this->true_displacements, 0); - -for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) =this->true_displacements(i)-moyenne+mean_displacement; - -} - - STOPTIMER("updateDisplacements"); - - - + Real moyenne = SurfaceStatistics::computeAverage(this->true_displacements, 0); + for (UInt i = 0; i < size; ++i) { + this->true_displacements(i) = + this->true_displacements(i) - moyenne + mean_displacement; + } } /* -------------------------------------------------------------------------- */ void BemPenalty::computePressures(Real mean_displacement) { - - this->computeTractionsFromDisplacements(); - this->functional->computeGradFU(); - //const Surface & gradF = this->functional->getGradF(); - //Real min = SurfaceStatistics::computeMinimum(gradF); - this->surface_tractions -= this->surface_tractions(0); - - - + this->computeTractionsFromDisplacements(); + this->functional->computeGradFU(); + // const Surface & gradF = this->functional->getGradF(); + // Real min = SurfaceStatistics::computeMinimum(gradF); + this->surface_tractions -= this->surface_tractions(0); } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_penalty.hh b/src/bem/bem_penalty.hh index 532d820..6b7501d 100644 --- a/src/bem/bem_penalty.hh +++ b/src/bem/bem_penalty.hh @@ -1,93 +1,92 @@ /** * * @author Valentine Rey * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_PENALTY_H #define BEM_PENALTY_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemPenalty : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemPenalty(Surface & p) : - BemFFTBase(p), - search_direction(p.size(), p.getL()), - surface_t(p.size(),p.getL()), - surface_r(p.size(),p.getL()), - mean_disp_search_direction(p.size(), p.getL()) { + BemPenalty(Surface& p) + : BemFFTBase(p), search_direction(p.size(), p.getL()), + surface_t(p.size(), p.getL()), surface_r(p.size(), p.getL()), + mean_disp_search_direction(p.size(), p.getL()) { e_star = 1.; max_iterations = 10000; }; virtual ~BemPenalty(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: //! compute the equilibrium situation - Real computeEquilibrium(Real epsilon,Real pressure,Real penalization_parameter); - void computeSearchDirection(Real mean_displacement,Real penalization_parameter); + Real computeEquilibrium(Real epsilon, Real pressure, + Real penalization_parameter); + void computeSearchDirection(Real mean_displacement, + Real penalization_parameter); void updateUnknown(Real tau, Real mean_displacement); Real computeStoppingCriterion(); - void computePressures(Real mean_displacement); - Real computeOptimalStep(); + void computePressures(Real mean_displacement); + Real computeOptimalStep(); -virtual void computeTractionsFromDisplacements(); + virtual void computeTractionsFromDisplacements(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! get the number of iterations - UInt getNbIterations() const{return this->nb_iterations;}; + UInt getNbIterations() const { return this->nb_iterations; }; //! get the convergence steps of iterations - const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + const std::vector& getConvergenceIterations() const { + return this->convergence_iterations; + }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! exploration direction for the Gigi algo Surface search_direction; //! exploration direction for the polonski algo Surface surface_t; //! projected exploration direction for the polonski algo Surface surface_r; //! exploration direction for optimization of mean displacement Surface mean_disp_search_direction; }; __END_TAMAAS__ #endif /* BEM_PENALTY_H */ diff --git a/src/bem/bem_polonski.cpp b/src/bem/bem_polonski.cpp index dfd2819..9de1d11 100644 --- a/src/bem/bem_polonski.cpp +++ b/src/bem/bem_polonski.cpp @@ -1,508 +1,466 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include -#include "surface.hh" #include "bem_polonski.hh" #include "fft_plan_manager.hh" #include "fftransform.hh" -#include -#include +#include "surface.hh" #include #include +#include #include -#include -/* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -BemPolonski::BemPolonski(Surface & p) : - BemFFTBase(p), - surface_t(p.size(),p.getL()), - surface_r(p.size(),p.getL()), - pold(p.size(),p.getL()), - p_sat(-1.){ - e_star = 1.; - max_iterations = 2000; - surface_rms_heights = SurfaceStatistics::computeStdev(this->surface); +BemPolonski::BemPolonski(Surface& p) + : BemFFTBase(p), surface_t(p.size(), p.getL()), + surface_r(p.size(), p.getL()), pold(p.size(), p.getL()), p_sat(-1.) { + e_star = 1.; + max_iterations = 2000; + surface_rms_heights = SurfaceStatistics::computeStdev(this->surface); } /* -------------------------------------------------------------------------- */ BemPolonski::~BemPolonski() {} /* -------------------------------------------------------------------------- */ -Real BemPolonski::computeEquilibrium(Real epsilon, - Real pressure) { - this->computeSpectralInfluenceOverDisplacement(); - this->surface_t = 0.; - this->surface_r = 0.; - this->pold = 0.; - this->surface_displacements = 0.; - Real delta = 0.; - Real Gold = 1.; - Real f = 1e300; - Real fPrevious = 1e300; - - Real current_pressure = SurfaceStatistics::computeAverage(surface_tractions); - std::cout << "current pressure "<enforcePressureBalance(pressure); - convergence_iterations.clear(); - nb_iterations = 0; - - while(f > epsilon && nb_iterations < max_iterations) { - fPrevious = f; - this->computeDisplacementsFromTractions(); - this->computeGaps(); - - Real gbar = this->computeMeanGapsInContact(); - - this->gap -= gbar; - Real G = this->computeG(); - +Real BemPolonski::computeEquilibrium(Real epsilon, Real pressure) { + this->computeSpectralInfluenceOverDisplacement(); + this->surface_t = 0.; + this->surface_r = 0.; + this->pold = 0.; + this->surface_displacements = 0.; + Real delta = 0.; + Real Gold = 1.; + Real f = 1e300; + Real fPrevious = 1e300; + + Real current_pressure = SurfaceStatistics::computeAverage(surface_tractions); + std::cout << "current pressure " << current_pressure << std::endl; + if (current_pressure <= 0.) + surface_tractions = pressure; + this->enforcePressureBalance(pressure); + convergence_iterations.clear(); + nb_iterations = 0; + + while (f > epsilon && nb_iterations < max_iterations) { + fPrevious = f; + this->computeDisplacementsFromTractions(); + this->computeGaps(); + + Real gbar = this->computeMeanGapsInContact(); + + this->gap -= gbar; + Real G = this->computeG(); + + this->updateT(G, Gold, delta); + Real tau = this->computeTau(); + pold = this->surface_tractions; + Gold = G; + delta = this->updateTractions(tau); + + // Projection on admissible space - this->updateT(G,Gold,delta); - Real tau = this->computeTau(); - pold = this->surface_tractions; - Gold = G; - delta = this->updateTractions(tau); - - - //Projection on admissible space - - this->enforcePressureBalance(pressure); - // std::cout << std::scientific << std::setprecision(10) - // << SurfaceStatistics::computeAverage(surface_tractions) << std::fixed << std::endl; - // - - f = this->computeF(); + this->enforcePressureBalance(pressure); + // std::cout << std::scientific << std::setprecision(10) + // << SurfaceStatistics::computeAverage(surface_tractions) << + // std::fixed << std::endl; + // - if (nb_iterations % dump_freq == 0){ - Real A = SurfaceStatistics::computeContactAreaRatio(surface_tractions); + f = this->computeF(); - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f << " " << f-fPrevious << " " << A - << std::fixed << std::endl; - } + if (nb_iterations % dump_freq == 0) { + Real A = SurfaceStatistics::computeContactAreaRatio(surface_tractions); - convergence_iterations.push_back(f); - ++nb_iterations; + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f << " " << f - fPrevious << " " << A << std::fixed + << std::endl; } - this->computeTrueDisplacements(); - return f; + + convergence_iterations.push_back(f); + ++nb_iterations; + } + this->computeTrueDisplacements(); + return f; } /* -------------------------------------------------------------------------- */ -Real BemPolonski::computeEquilibriuminit(Real epsilon, - Real pressure, Surface & init) { - this->computeSpectralInfluenceOverDisplacement(); - this->surface_t = 0.; - this->surface_r = 0.; - this->pold = 0.; - this->surface_displacements = 0.; - Real delta = 0.; - Real Gold = 1.; - Real f = 1e300; - Real fPrevious = 1e300; - - this->surface_tractions=init; - Real current_pressure = SurfaceStatistics::computeAverage(surface_tractions); - if (current_pressure <= 0.) surface_tractions = pressure; - this->enforcePressureBalance(pressure); - convergence_iterations.clear(); - nb_iterations = 0; - this->computeDisplacementsFromTractions(); - f=this->computeF(); - - std::cout << std::scientific << std::setprecision(10) - <<" " - << f << std::endl; - - - while(f > epsilon && nb_iterations < max_iterations) { - fPrevious = f; - this->computeDisplacementsFromTractions(); - this->computeGaps(); - - Real gbar = this->computeMeanGapsInContact(); - - this->gap -= gbar; - Real G = this->computeG(); +Real BemPolonski::computeEquilibriuminit(Real epsilon, Real pressure, + Surface& init) { + this->computeSpectralInfluenceOverDisplacement(); + this->surface_t = 0.; + this->surface_r = 0.; + this->pold = 0.; + this->surface_displacements = 0.; + Real delta = 0.; + Real Gold = 1.; + Real f = 1e300; + Real fPrevious = 1e300; + + this->surface_tractions = init; + Real current_pressure = SurfaceStatistics::computeAverage(surface_tractions); + if (current_pressure <= 0.) + surface_tractions = pressure; + this->enforcePressureBalance(pressure); + convergence_iterations.clear(); + nb_iterations = 0; + this->computeDisplacementsFromTractions(); + f = this->computeF(); + + std::cout << std::scientific << std::setprecision(10) << " " << f + << std::endl; + + while (f > epsilon && nb_iterations < max_iterations) { + fPrevious = f; + this->computeDisplacementsFromTractions(); + this->computeGaps(); + + Real gbar = this->computeMeanGapsInContact(); + + this->gap -= gbar; + Real G = this->computeG(); + + this->updateT(G, Gold, delta); + Real tau = this->computeTau(); + pold = this->surface_tractions; + Gold = G; + delta = this->updateTractions(tau); + + // Projection on admissible space + this->enforcePressureBalance(pressure); + // std::cout << std::scientific << std::setprecision(10) + // << SurfaceStatistics::computeAverage(surface_tractions) << + // std::fixed << std::endl; + // - this->updateT(G,Gold,delta); - Real tau = this->computeTau(); - pold = this->surface_tractions; - Gold = G; - delta = this->updateTractions(tau); - - - //Projection on admissible space - - this->enforcePressureBalance(pressure); - // std::cout << std::scientific << std::setprecision(10) - // << SurfaceStatistics::computeAverage(surface_tractions) << std::fixed << std::endl; - // - - f = this->computeF(); - - if (nb_iterations % dump_freq == 0){ - Real A = SurfaceStatistics::computeContactAreaRatio(surface_tractions); + f = this->computeF(); - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f << " " << f-fPrevious << " " << A - << std::fixed << std::endl; - } + if (nb_iterations % dump_freq == 0) { + Real A = SurfaceStatistics::computeContactAreaRatio(surface_tractions); - convergence_iterations.push_back(f); - ++nb_iterations; + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f << " " << f - fPrevious << " " << A << std::fixed + << std::endl; } - this->computeTrueDisplacements(); - return f; + + convergence_iterations.push_back(f); + ++nb_iterations; + } + this->computeTrueDisplacements(); + return f; } /* -------------------------------------------------------------------------- */ - void BemPolonski::computeGaps() { - UInt size = surface.size(); + UInt size = surface.size(); #pragma omp parallel for - for (UInt i=0; i < size*size; i++) { - gap(i) = surface_displacements(i) - surface(i); - } + for (UInt i = 0; i < size * size; i++) { + gap(i) = surface_displacements(i) - surface(i); + } } - /* -------------------------------------------------------------------------- */ -Real BemPolonski::computeMeanGapsInContact(){ - STARTTIMER("computeMeanGapsInContact"); - - UInt n = surface.size(); - UInt size = n*n; - Real res = 0.; - UInt nb_contact = 0; -#pragma omp parallel for reduction(+: nb_contact,res) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0 ||std::abs(this->surface_tractions(i) - p_sat)< 1.0e-10 ) continue; - ++nb_contact; - res += this->gap(i); - } - - res /= nb_contact; - STOPTIMER("computeMeanGapsInContact"); - return res; +Real BemPolonski::computeMeanGapsInContact() { + UInt n = surface.size(); + UInt size = n * n; + Real res = 0.; + UInt nb_contact = 0; +#pragma omp parallel for reduction(+ : nb_contact, res) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0 || + std::abs(this->surface_tractions(i) - p_sat) < 1.0e-10) + continue; + ++nb_contact; + res += this->gap(i); + } + + res /= nb_contact; + return res; } /* -------------------------------------------------------------------------- */ -Real BemPolonski::computeG(){ - STARTTIMER("computeG"); - - UInt n = surface.size(); - UInt size = n*n; - Real res = 0.; -#pragma omp parallel for reduction(+: res) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0 ||std::abs(this->surface_tractions(i) - p_sat)< 1.0e-10 ) continue; - Real val = this->gap(i); - res += val*val; - } - - STOPTIMER("computeG"); - return res; +Real BemPolonski::computeG() { + UInt n = surface.size(); + UInt size = n * n; + Real res = 0.; +#pragma omp parallel for reduction(+ : res) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0 || + std::abs(this->surface_tractions(i) - p_sat) < 1.0e-10) + continue; + Real val = this->gap(i); + res += val * val; + } + + return res; } /* -------------------------------------------------------------------------- */ - -void BemPolonski::updateT(Real G, Real Gold, Real delta){ - STARTTIMER("updateT"); - - UInt n = surface.size(); - UInt size = n*n; - Real factor = delta*G/Gold; +void BemPolonski::updateT(Real G, Real Gold, Real delta) { + UInt n = surface.size(); + UInt size = n * n; + Real factor = delta * G / Gold; #pragma omp parallel for - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0) this->surface_t(i) = 0.; - else{ - this->surface_t(i) *= factor; - this->surface_t(i) += this->gap(i); - } + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0) + this->surface_t(i) = 0.; + else { + this->surface_t(i) *= factor; + this->surface_t(i) += this->gap(i); } - - STOPTIMER("updateT"); + } } - /* -------------------------------------------------------------------------- */ -Real BemPolonski::computeTau(){ - STARTTIMER("computeTau"); - - this->applyInfluenceFunctions(surface_t, surface_r); - - const UInt size = surface_t.size() * surface_t.size(); - - Real rbar = 0; - UInt nb_contact = 0; -#pragma omp parallel for reduction(+: nb_contact,rbar) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0) continue; - ++nb_contact; - rbar += surface_r(i); - } - rbar /= nb_contact; - surface_r -= rbar; - - Real tau_sum1 = 0.,tau_sum2 = 0.; - -#pragma omp parallel for reduction(+: tau_sum1, tau_sum2) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0) continue; - tau_sum1 += this->gap(i)*surface_t(i); - tau_sum2 += surface_r(i)*surface_t(i); - } - Real tau = tau_sum1/tau_sum2; - - STOPTIMER("computeTau"); - return tau; +Real BemPolonski::computeTau() { + this->applyInfluenceFunctions(surface_t, surface_r); + + const UInt size = surface_t.size() * surface_t.size(); + + Real rbar = 0; + UInt nb_contact = 0; +#pragma omp parallel for reduction(+ : nb_contact, rbar) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0) + continue; + ++nb_contact; + rbar += surface_r(i); + } + rbar /= nb_contact; + surface_r -= rbar; + + Real tau_sum1 = 0., tau_sum2 = 0.; + +#pragma omp parallel for reduction(+ : tau_sum1, tau_sum2) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0) + continue; + tau_sum1 += this->gap(i) * surface_t(i); + tau_sum2 += surface_r(i) * surface_t(i); + } + Real tau = tau_sum1 / tau_sum2; + + return tau; } - - /* -------------------------------------------------------------------------- */ -Real BemPolonski::updateTractions(Real tau){ - STARTTIMER("updateTractions"); - - UInt n = surface.size(); - UInt size = n*n; +Real BemPolonski::updateTractions(Real tau) { + UInt n = surface.size(); + UInt size = n * n; #pragma omp parallel for - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0) continue; - this->surface_tractions(i) -= tau*this->surface_t(i); - if (this->surface_tractions(i) < 0.) this->surface_tractions(i) = 0; + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0) + continue; + this->surface_tractions(i) -= tau * this->surface_t(i); + if (this->surface_tractions(i) < 0.) + this->surface_tractions(i) = 0; + } + + // compute number of interpenetration without contact + UInt nb_iol = 0; +#pragma omp parallel for reduction(+ : nb_iol) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0. && this->gap(i) < 0.) { + this->surface_tractions(i) -= tau * this->gap(i); + ++nb_iol; } - - //compute number of interpenetration without contact - UInt nb_iol = 0; -#pragma omp parallel for reduction(+: nb_iol) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) <= 0. && - this->gap(i) < 0.) { - this->surface_tractions(i) -= tau*this->gap(i); - ++nb_iol; - } - } - - - //compute number of interpenetration without contact - UInt nb_sl = 0; -#pragma omp parallel for reduction(+: nb_sl) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) ==p_sat && - 0.< this->gap(i) ) { - this->surface_tractions(i) -= tau*this->gap(i); - ++nb_sl; - } + } + + // compute number of interpenetration without contact + UInt nb_sl = 0; +#pragma omp parallel for reduction(+ : nb_sl) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) == p_sat && 0. < this->gap(i)) { + this->surface_tractions(i) -= tau * this->gap(i); + ++nb_sl; } + } + Real delta = 0; + if (nb_iol > 0 || nb_sl > 0) + delta = 0.; + else + delta = 1.; - - - Real delta = 0; - if (nb_iol > 0 || nb_sl> 0) delta = 0.; - else delta = 1.; - - STOPTIMER("updateTractions"); - return delta; + return delta; } /* -------------------------------------------------------------------------- */ -void BemPolonski::enforcePressureBalance(Real applied_pressure){ - STARTTIMER("enforcePressureBalance"); - - UInt n = surface.size(); - UInt size = n*n; +void BemPolonski::enforcePressureBalance(Real applied_pressure) { + UInt n = surface.size(); + UInt size = n * n; - - // If we have no saturation, scale to match applied_pressure - if (this->p_sat <= 0. || - SurfaceStatistics::computeMaximum(this->surface_tractions) < this->p_sat) { - Real pressure = 0.; -#pragma omp parallel for reduction(+: pressure) - for (UInt i = 0; i < size; ++i) { - pressure += this->surface_tractions(i); - } - - pressure *= 1./size; - this->surface_tractions *= applied_pressure/pressure; + // If we have no saturation, scale to match applied_pressure + if (this->p_sat <= 0. || SurfaceStatistics::computeMaximum( + this->surface_tractions) < this->p_sat) { + Real pressure = 0.; +#pragma omp parallel for reduction(+ : pressure) + for (UInt i = 0; i < size; ++i) { + pressure += this->surface_tractions(i); } - // If we have saturation, use secant method to find zero of saturationFunction - else { - - - - - // Checking if we can find a zero - Real limit = - this->p_sat * SurfaceStatistics::computeContactArea(this->surface_tractions) - - applied_pressure; - if (limit < 0) SURFACE_FATAL("Saturation pressure is too small for applied pressure"); - - // Initial points - Real x_n_2 = 0., x_n_1 = 1., x_n = 0.; - Real f_n_2 = 0., f_n_1 = 0., f_n = 0.; - - // Secant loop - do { - f_n_2 = saturationFunction(x_n_2, applied_pressure); - f_n_1 = saturationFunction(x_n_1, applied_pressure); - x_n = x_n_1 - f_n_1 * (x_n_1 - x_n_2) / (f_n_1 - f_n_2); - f_n = saturationFunction(x_n, applied_pressure); - x_n_2 = x_n_1; - x_n_1 = x_n; - } while (std::abs(f_n) > 1e-16); - - this->surface_tractions *= x_n; - // Truncating pressures - #pragma omp parallel for - for (UInt i = 0 ; i < size ; i++) { - if (this->surface_tractions(i) > this->p_sat) - this->surface_tractions(i) = this->p_sat; - } -// Real mu_I_sat=0.; -// #pragma omp parallel for reduction(+: mu_I_sat) -// for (UInt i = 0; i < size; ++i) { -// if ( this->p_sat< this->surface_tractions(i) ){ -// mu_I_sat+=1.; -// } -// } - - -// Real pc=0.; -// #pragma omp parallel for reduction(+: pc) -// for (UInt i = 0; i < size; ++i) { -// if ( this->surface_tractions(i) < this->p_sat ){ -// pc+=this->surface_tractions(i);} -// } - -// #pragma omp parallel for -// for (UInt i = 0; i < size; ++i) { -// if ( this->surface_tractions(i) < this->p_sat ){ -// this->surface_tractions(i)= this->surface_tractions(i)*((size*applied_pressure-this->p_sat*mu_I_sat)/pc);} -// } -// #pragma omp parallel for -// for (UInt i = 0; i < size; ++i) { -// if ( this->p_sat< this->surface_tractions(i) ){ -// this->surface_tractions(i)=this->p_sat; -// } -// } - - + pressure *= 1. / size; + this->surface_tractions *= applied_pressure / pressure; + } + + // If we have saturation, use secant method to find zero of saturationFunction + else { + + // Checking if we can find a zero + Real limit = this->p_sat * SurfaceStatistics::computeContactArea( + this->surface_tractions) - + applied_pressure; + if (limit < 0) + SURFACE_FATAL("Saturation pressure is too small for applied pressure"); + + // Initial points + Real x_n_2 = 0., x_n_1 = 1., x_n = 0.; + Real f_n_2 = 0., f_n_1 = 0., f_n = 0.; + + // Secant loop + do { + f_n_2 = saturationFunction(x_n_2, applied_pressure); + f_n_1 = saturationFunction(x_n_1, applied_pressure); + x_n = x_n_1 - f_n_1 * (x_n_1 - x_n_2) / (f_n_1 - f_n_2); + f_n = saturationFunction(x_n, applied_pressure); + x_n_2 = x_n_1; + x_n_1 = x_n; + } while (std::abs(f_n) > 1e-16); + + this->surface_tractions *= x_n; + // Truncating pressures +#pragma omp parallel for + for (UInt i = 0; i < size; i++) { + if (this->surface_tractions(i) > this->p_sat) + this->surface_tractions(i) = this->p_sat; } - - - - - - STOPTIMER("enforcePressureBalance"); + // Real mu_I_sat=0.; + // #pragma omp parallel for reduction(+: mu_I_sat) + // for (UInt i = 0; i < size; ++i) { + // if ( this->p_sat< this->surface_tractions(i) ){ + // mu_I_sat+=1.; + // } + // } + + // Real pc=0.; + // #pragma omp parallel for reduction(+: pc) + // for (UInt i = 0; i < size; ++i) { + // if ( this->surface_tractions(i) < this->p_sat ){ + // pc+=this->surface_tractions(i);} + // } + + // #pragma omp parallel for + // for (UInt i = 0; i < size; ++i) { + // if ( this->surface_tractions(i) < this->p_sat ){ + // this->surface_tractions(i)= + // this->surface_tractions(i)*((size*applied_pressure-this->p_sat*mu_I_sat)/pc);} + // } + // #pragma omp parallel for + // for (UInt i = 0; i < size; ++i) { + // if ( this->p_sat< this->surface_tractions(i) ){ + // this->surface_tractions(i)=this->p_sat; + // } + // } + } } /* -------------------------------------------------------------------------- */ Real BemPolonski::saturationFunction(Real alpha, Real applied_pressure) { - const UInt n = surface.size(); - const UInt size = n*n; - Real sum = 0.; -#pragma omp parallel for reduction(+: sum) - for (UInt i = 0 ; i < size ; i++) { - Real alpha_p = alpha * this->surface_tractions(i); - Real alpha_p_I = (alpha_p > this->p_sat)? alpha_p - this->p_sat : 0.; - sum += alpha_p - alpha_p_I; - } - sum /= size; - return sum - applied_pressure; + const UInt n = surface.size(); + const UInt size = n * n; + Real sum = 0.; +#pragma omp parallel for reduction(+ : sum) + for (UInt i = 0; i < size; i++) { + Real alpha_p = alpha * this->surface_tractions(i); + Real alpha_p_I = (alpha_p > this->p_sat) ? alpha_p - this->p_sat : 0.; + sum += alpha_p - alpha_p_I; + } + sum /= size; + return sum - applied_pressure; } /* -------------------------------------------------------------------------- */ Real BemPolonski::computeF() { - UInt n = surface.size(); - UInt size = n*n; - - Real res = 0; - - Real t_sum = SurfaceStatistics::computeSum(surface_tractions); - computeTrueDisplacements(); -#pragma omp parallel for reduction(+:res) - for (UInt i = 0; i < size; ++i) { - if (this->surface_tractions(i) == this->p_sat) continue; - res += surface_tractions(i) * ( this->true_displacements(i)-surface(i)); - // res += - // this->surface_tractions[i].real() - // *(surface_displacements[i].real() - surface[i].real()); - } - - return std::abs(res/t_sum/surface_rms_heights/size); + UInt n = surface.size(); + UInt size = n * n; + + Real res = 0; + + Real t_sum = SurfaceStatistics::computeSum(surface_tractions); + computeTrueDisplacements(); +#pragma omp parallel for reduction(+ : res) + for (UInt i = 0; i < size; ++i) { + if (this->surface_tractions(i) == this->p_sat) + continue; + res += surface_tractions(i) * (this->true_displacements(i) - surface(i)); + // res += + // this->surface_tractions[i].real() + // *(surface_displacements[i].real() - surface[i].real()); + } + + return std::abs(res / t_sum / surface_rms_heights / size); } /* -------------------------------------------------------------------------- */ -void BemPolonski::computeTrueDisplacements(){ - this->applyInfluenceFunctions(this->surface_tractions, this->surface_displacements); - - this->true_displacements = this->surface_displacements; +void BemPolonski::computeTrueDisplacements() { + this->applyInfluenceFunctions(this->surface_tractions, + this->surface_displacements); - UInt n = surface.size(); - UInt size = n*n; + this->true_displacements = this->surface_displacements; - Real shift = 1e300; + UInt n = surface.size(); + UInt size = n * n; + Real shift = 1e300; -#pragma omp parallel for reduction(min:shift) - for (UInt i = 0; i < size; ++i) { +#pragma omp parallel for reduction(min : shift) + for (UInt i = 0; i < size; ++i) { - if (surface_displacements(i) - shift - surface(i) < 0. &&( this->p_sat < 0 || this->surface_tractions(i) < this->p_sat )){ - shift = surface_displacements(i) - surface(i); - } + if (surface_displacements(i) - shift - surface(i) < 0. && + (this->p_sat < 0 || this->surface_tractions(i) < this->p_sat)) { + shift = surface_displacements(i) - surface(i); } + } #pragma omp parallel for - for (UInt i = 0; i < size; ++i) { - true_displacements(i) = surface_displacements(i) - shift; - } - + for (UInt i = 0; i < size; ++i) { + true_displacements(i) = surface_displacements(i) - shift; + } } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_polonski.hh b/src/bem/bem_polonski.hh index 64aee47..c3a33ec 100644 --- a/src/bem/bem_polonski.hh +++ b/src/bem/bem_polonski.hh @@ -1,108 +1,105 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_POLONSKI_H #define BEM_POLONSKI_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemPolonski : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemPolonski(Surface & p); + BemPolonski(Surface& p); virtual ~BemPolonski(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: - - //! compute the equilibrium situation - Real computeEquilibrium(Real epsilon,Real pressure); - Real computeEquilibriuminit(Real epsilon,Real pressure, Surface & init); + Real computeEquilibrium(Real epsilon, Real pressure); + Real computeEquilibriuminit(Real epsilon, Real pressure, Surface& init); //! compute the mean of the gaps in the contact region Real computeMeanGapsInContact(); //! compute the non zero gap penalty functional Real computeG(); //! update the search direction void updateT(Real G, Real Gold, Real delta); //! compute the conjugate step size Real computeTau(); //! update the tractions Real updateTractions(Real tau); //! enforce the applied and contact pressures balance void enforcePressureBalance(Real applied_pressure); //! compute the gaps void computeGaps(); //! compute the gaps - void computeTrueDisplacements(); + void computeTrueDisplacements(); //! compute F Real computeF(); //! saturation function Real saturationFunction(Real alpha, Real applied_pressure); //! set saturation pressure - void setMaxPressure(Real p) {this->p_sat = p;} + void setMaxPressure(Real p) { this->p_sat = p; } /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! get the number of iterations - UInt getNbIterations() const{return this->nb_iterations;}; + UInt getNbIterations() const { return this->nb_iterations; }; //! get the convergence steps of iterations - const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + const std::vector& getConvergenceIterations() const { + return this->convergence_iterations; + }; - Surface & getSurfaceT(){return surface_t;}; + Surface& getSurfaceT() { return surface_t; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! exploration direction for the polonski algo Surface surface_t; //! projected exploration direction for the polonski algo Surface surface_r; //! previous pressure Surface pold; //! saturation pressure Real p_sat; //! the rms of heights of the surface Real surface_rms_heights; }; __END_TAMAAS__ #endif /* BEM_POLONSKI_H */ diff --git a/src/bem/bem_uzawa.cpp b/src/bem/bem_uzawa.cpp index 6ff7423..cd4e67d 100644 --- a/src/bem/bem_uzawa.cpp +++ b/src/bem/bem_uzawa.cpp @@ -1,322 +1,255 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include -#include "surface.hh" #include "bem_uzawa.hh" -#include -#include +#include "surface.hh" #include #include +#include #include -#include -/* -------------------------------------------------------------------------- */ -#define TIMER -#include "surface_timer.hh" +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ void BemUzawa::computeTractionsFromDisplacements() { - this->applyInverseInfluenceFunctions(this->true_displacements,this->surface_tractions); + this->applyInverseInfluenceFunctions(this->true_displacements, + this->surface_tractions); } -Real BemUzawa::computeEquilibrium(Real epsilon, - Real mean_displacement, Real penalization_parameter) { +Real BemUzawa::computeEquilibrium(Real epsilon, Real mean_displacement, + Real penalization_parameter) { this->computeSpectralInfluenceOverDisplacement(); this->search_direction = 0.; this->true_displacements = 0; this->true_displacements = mean_displacement; this->computeGaps(); this->multipliers = 0; - Real f_2 = 1e300; Real new_pen = 1e300; Real old_pen = 1e300; convergence_iterations.clear(); UInt nb_iterations_1 = 0; UInt nb_iterations_2 = 0; -std::ofstream file ("output.txt"); + std::ofstream file("output.txt"); Real max_iterations_1 = 500; - Real max_iterations_2 = 1000; + Real max_iterations_2 = 1000; - while (new_pen> epsilon && nb_iterations_1++ < max_iterations_1) { - std::cout << "iter ext "<< nb_iterations_1 << std::endl; + while (new_pen > epsilon && nb_iterations_1++ < max_iterations_1) { + std::cout << "iter ext " << nb_iterations_1 << std::endl; - - while (f_2> 1e-12 && nb_iterations_2++ < max_iterations_2) { - std::cout << "iter int "<< nb_iterations_2 << std::endl; + while (f_2 > 1e-12 && nb_iterations_2++ < max_iterations_2) { + std::cout << "iter int " << nb_iterations_2 << std::endl; this->functional->computeGradFU(); - this->computeSearchDirection(mean_displacement,penalization_parameter); + this->computeSearchDirection(mean_displacement, penalization_parameter); - Real alpha=1/(10*penalization_parameter); - this->old_displacements=this->true_displacements; - this->updateUnknown( alpha, mean_displacement); + Real alpha = 1 / (10 * penalization_parameter); + this->old_displacements = this->true_displacements; + this->updateUnknown(alpha, mean_displacement); this->computeGaps(); f_2 = computeStoppingCriterion(); if (nb_iterations_2 % dump_freq == 0) { - std::cout << std::scientific << std::setprecision(10) - << nb_iterations << " " - << f_2 << std::fixed << std::endl; - - - - this->computePressures(); - Real orth=0.; - UInt n = surface.size(); - UInt size = n*n; - - #pragma omp parallel for reduction(+:orth) - for (UInt i = 0; i < size; ++i) { - - orth += std::abs(surface_tractions(i) * ( this->true_displacements(i)-surface(i))); - - } - + std::cout << std::scientific << std::setprecision(10) << nb_iterations + << " " << f_2 << std::fixed << std::endl; + this->computePressures(); + Real orth = 0.; + UInt n = surface.size(); + UInt size = n * n; - file<< std::scientific << std::setprecision(10)<< nb_iterations_2 << " " - <true_displacements(i) - surface(i))); + } + file << std::scientific << std::setprecision(10) << nb_iterations_2 + << " " << f_2 << " " << orth << std::endl; } } this->updateMultipliers(penalization_parameter); - old_pen=computeInterpenetration(this->old_displacements); - new_pen=computeInterpenetration(this->true_displacements); - std::cout << "old penetration is "<< old_pen << std::endl; - std::cout << "new penetration is "<< new_pen << std::endl; + old_pen = computeInterpenetration(this->old_displacements); + new_pen = computeInterpenetration(this->true_displacements); + std::cout << "old penetration is " << old_pen << std::endl; + std::cout << "new penetration is " << new_pen << std::endl; - penalization_parameter=this->updatePenalization(penalization_parameter, old_pen, new_pen); - //to avoid ill conditioned system - if (penalization_parameter>1.0e8) new_pen=0.; + penalization_parameter = + this->updatePenalization(penalization_parameter, old_pen, new_pen); + // to avoid ill conditioned system + if (penalization_parameter > 1.0e8) + new_pen = 0.; nb_iterations_2 = 0; f_2 = 1e300; - std::cout << "penalization is "<< penalization_parameter << std::endl; - + std::cout << "penalization is " << penalization_parameter << std::endl; } this->computeGaps(); this->computePressures(); - - return new_pen; } /* -------------------------------------------------------------------------- */ Real BemUzawa::computeStoppingCriterion() { - - Real crit=0.; + Real crit = 0.; Real disp_norm = 0.; UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; -#pragma omp parallel for reduction(+:crit, disp_norm) +#pragma omp parallel for reduction(+ : crit, disp_norm) for (UInt i = 0; i < size; ++i) { - - crit += (this->search_direction(i))*(this->search_direction(i)); - disp_norm += (true_displacements(i)*true_displacements(i)); + crit += (this->search_direction(i)) * (this->search_direction(i)); + disp_norm += (true_displacements(i) * true_displacements(i)); } - - return crit / disp_norm; } /* -------------------------------------------------------------------------- */ -void BemUzawa::computeSearchDirection(Real mean_displacement,Real penalization_parameter) { - STARTTIMER("computeOptimalStep"); - - +void BemUzawa::computeSearchDirection(Real mean_displacement, + Real penalization_parameter) { UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; - const Surface & gradF = this->functional->getGradF(); + const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 1; i < size; ++i) { - this->search_direction(i)=gradF(i); - - if (this->multipliers(i)+penalization_parameter*gap(i)<=0){ + this->search_direction(i) = gradF(i); + if (this->multipliers(i) + penalization_parameter * gap(i) <= 0) { - this->search_direction(i)=this->search_direction(i)+ this->multipliers(i)+penalization_parameter*gap(i); + this->search_direction(i) = this->search_direction(i) + + this->multipliers(i) + + penalization_parameter * gap(i); } - } - - - } /* -------------------------------------------------------------------------- */ Real BemUzawa::computeOptimalStep() { - STARTTIMER("computeOptimalStep"); - this->applyInverseInfluenceFunctions(search_direction, surface_r); UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; Real numerator = 0., denominator = 0.; -#pragma omp parallel for reduction(+: numerator, denominator) +#pragma omp parallel for reduction(+ : numerator, denominator) for (UInt i = 0; i < size; ++i) { numerator += search_direction(i) * search_direction(i); denominator += surface_r(i) * search_direction(i); } Real alpha = numerator / denominator; - STOPTIMER("computeOptimalStep"); return alpha; - - - } - /* -------------------------------------------------------------------------- */ void BemUzawa::updateMultipliers(Real penalization_parameter) { - STARTTIMER("updateMultipliers"); - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - if (this->multipliers(i)+penalization_parameter*gap(i)>0.){ + if (this->multipliers(i) + penalization_parameter * gap(i) > 0.) { this->multipliers(i) = 0; + } else { + this->multipliers(i) += penalization_parameter * gap(i); } - else{ - this->multipliers(i)+=penalization_parameter*gap(i); - } - - } - - - - STOPTIMER("updateMultipliers"); } /* -------------------------------------------------------------------------- */ -Real BemUzawa::updatePenalization(Real penalization_parameter, Real old_pen, Real new_pen) { - STARTTIMER("updatePenalization"); - - - if (new_pen>0.25*old_pen){ - penalization_parameter*=5; +Real BemUzawa::updatePenalization(Real penalization_parameter, Real old_pen, + Real new_pen) { + if (new_pen > 0.25 * old_pen) { + penalization_parameter *= 5; } - return penalization_parameter; - - - - - STOPTIMER("updatePenalization"); } - /* -------------------------------------------------------------------------- */ -Real BemUzawa::computeInterpenetration( Surface & displacements ) { - STARTTIMER("updateMultipliers"); - +Real BemUzawa::computeInterpenetration(Surface& displacements) { UInt n = surface.size(); - UInt size = n*n; - Real res=0.; + UInt size = n * n; + Real res = 0.; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - if (0>this->true_displacements(i)-surface(i)){ - res+=(this->true_displacements(i)-surface(i))*(this->true_displacements(i)-surface(i)); + if (0 > this->true_displacements(i) - surface(i)) { + res += (this->true_displacements(i) - surface(i)) * + (this->true_displacements(i) - surface(i)); } - } return sqrt(res); - - - - STOPTIMER("updateMultipliers"); } - /* -------------------------------------------------------------------------- */ - void BemUzawa::updateUnknown(Real alpha, Real mean_displacement) { - STARTTIMER("updateDisplacements"); - UInt n = surface.size(); - UInt size = n*n; + UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) -= alpha*this->search_direction(i); - + this->true_displacements(i) -= alpha * this->search_direction(i); } - Real moyenne=SurfaceStatistics::computeAverage(this->true_displacements, 0); + Real moyenne = SurfaceStatistics::computeAverage(this->true_displacements, 0); for (UInt i = 0; i < size; ++i) { - this->true_displacements(i) =this->true_displacements(i)-moyenne+mean_displacement; - + this->true_displacements(i) = + this->true_displacements(i) - moyenne + mean_displacement; } - - - - STOPTIMER("updateDisplacements"); } /* -------------------------------------------------------------------------- */ - void BemUzawa::computePressures() { - - - this->computeTractionsFromDisplacements(); - this->functional->computeGradFU(); - //const Surface & gradF = this->functional->getGradF(); - //Real min = SurfaceStatistics::computeMinimum(gradF); - this->surface_tractions -= this->surface_tractions(0); + this->computeTractionsFromDisplacements(); + this->functional->computeGradFU(); + // const Surface & gradF = this->functional->getGradF(); + // Real min = SurfaceStatistics::computeMinimum(gradF); + this->surface_tractions -= this->surface_tractions(0); } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_uzawa.hh b/src/bem/bem_uzawa.hh index bcb9bdf..483c0d3 100644 --- a/src/bem/bem_uzawa.hh +++ b/src/bem/bem_uzawa.hh @@ -1,94 +1,94 @@ /** * * @author Valentine Rey * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef BEM_UZAWA_H #define BEM_UZAWA_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ class BemUzawa : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - - BemUzawa(Surface & p) : - BemFFTBase(p), - search_direction(p.size(), p.getL()), - multipliers(p.size(),p.getL()), - surface_r(p.size(),p.getL()), - mean_disp_search_direction(p.size(), p.getL()) { + BemUzawa(Surface& p) + : BemFFTBase(p), search_direction(p.size(), p.getL()), + multipliers(p.size(), p.getL()), surface_r(p.size(), p.getL()), + mean_disp_search_direction(p.size(), p.getL()) { e_star = 1.; max_iterations = 10000; }; virtual ~BemUzawa(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: //! compute the equilibrium situation - Real computeEquilibrium(Real epsilon,Real pressure,Real penalization_parameter); - void computeSearchDirection(Real mean_displacement,Real penalization_parameter); + Real computeEquilibrium(Real epsilon, Real pressure, + Real penalization_parameter); + void computeSearchDirection(Real mean_displacement, + Real penalization_parameter); void updateMultipliers(Real penalization_parameter); - Real updatePenalization(Real penalization_parameter, Real old_pen, Real new_pen); - Real computeInterpenetration( Surface & displacements ) ; + Real updatePenalization(Real penalization_parameter, Real old_pen, + Real new_pen); + Real computeInterpenetration(Surface& displacements); void updateUnknown(Real tau, Real mean_displacement); Real computeStoppingCriterion(); void computePressures(); Real computeOptimalStep(); -virtual void computeTractionsFromDisplacements(); + virtual void computeTractionsFromDisplacements(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - //! get the number of iterations - UInt getNbIterations() const{return this->nb_iterations;}; + UInt getNbIterations() const { return this->nb_iterations; }; //! get the convergence steps of iterations - const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + const std::vector& getConvergenceIterations() const { + return this->convergence_iterations; + }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - //! exploration direction for the Gigi algo Surface search_direction; //! exploration direction for the polonski algo Surface multipliers; //! projected exploration direction for the polonski algo Surface surface_r; //! exploration direction for optimization of mean displacement Surface mean_disp_search_direction; }; __END_TAMAAS__ #endif /* BEM_Uzawa_H */ diff --git a/src/bem/complimentary_term_functional.cpp b/src/bem/complimentary_term_functional.cpp index 9204711..3739739 100644 --- a/src/bem/complimentary_term_functional.cpp +++ b/src/bem/complimentary_term_functional.cpp @@ -1,60 +1,59 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "complimentary_term_functional.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -ComplimentaryTermFunctional::ComplimentaryTermFunctional(BemFFTBase & bem): - Functional(bem) -{} +ComplimentaryTermFunctional::ComplimentaryTermFunctional(BemFFTBase& bem) + : Functional(bem) {} -ComplimentaryTermFunctional::~ComplimentaryTermFunctional() -{} +ComplimentaryTermFunctional::~ComplimentaryTermFunctional() {} Real ComplimentaryTermFunctional::computeF() { - const Surface & tractions = bem.getTractions(); - const Surface & surface = bem.getSurface(); + const Surface& tractions = bem.getTractions(); + const Surface& surface = bem.getSurface(); Real F = 0; UInt n = surface.size(); UInt size = n * n; -#pragma omp parallel for reduction(+: F) - for (UInt i = 0 ; i < size ; ++i) +#pragma omp parallel for reduction(+ : F) + for (UInt i = 0; i < size; ++i) F += tractions(i) * surface(i); return F; } void ComplimentaryTermFunctional::computeGradFP() { *this->gradF -= bem.getSurface(); } void ComplimentaryTermFunctional::computeGradFU() { - SURFACE_FATAL("complimentary term cannot be differentiated with respect to u"); + SURFACE_FATAL( + "complimentary term cannot be differentiated with respect to u"); } __END_TAMAAS__ diff --git a/src/bem/complimentary_term_functional.hh b/src/bem/complimentary_term_functional.hh index de0573f..5a77ce7 100644 --- a/src/bem/complimentary_term_functional.hh +++ b/src/bem/complimentary_term_functional.hh @@ -1,58 +1,59 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __COMPLIMENTARY_TERM_FUNCTIONAL_HH__ #define __COMPLIMENTARY_TERM_FUNCTIONAL_HH__ -#include "bem_functional.hh" #include "bem_fft_base.hh" +#include "bem_functional.hh" __BEGIN_TAMAAS__ -/// Energy functional (in displacement) that contains the adhesion term from Müser's contest +/// Energy functional (in displacement) that contains the adhesion term from +/// Müser's contest class ComplimentaryTermFunctional : public Functional { public: /// Constructor - explicit ComplimentaryTermFunctional(BemFFTBase & bem); + explicit ComplimentaryTermFunctional(BemFFTBase& bem); /// Destructor virtual ~ComplimentaryTermFunctional(); public: /// Compute value of objective function virtual Real computeF(); /// Compute gradient of objective function virtual void computeGradFU(); /// Compute gradient of objective function virtual void computeGradFP(); }; __END_TAMAAS__ -#endif //__COMPLIMENTARY_TERM_FUNCTIONAL_HH__ +#endif //__COMPLIMENTARY_TERM_FUNCTIONAL_HH__ diff --git a/src/bem/elastic_energy_functional.cpp b/src/bem/elastic_energy_functional.cpp index 6a59fa2..bff6800 100644 --- a/src/bem/elastic_energy_functional.cpp +++ b/src/bem/elastic_energy_functional.cpp @@ -1,78 +1,75 @@ /** * * @author Lucas Frérot * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "elastic_energy_functional.hh" -#include "surface_statistics.hh" #include "bem_fft_base.hh" +#include "surface_statistics.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -ElasticEnergyFunctional::ElasticEnergyFunctional(BemFFTBase & bem): - Functional(bem) -{} +ElasticEnergyFunctional::ElasticEnergyFunctional(BemFFTBase& bem) + : Functional(bem) {} /* -------------------------------------------------------------------------- */ -ElasticEnergyFunctional::~ElasticEnergyFunctional() -{} +ElasticEnergyFunctional::~ElasticEnergyFunctional() {} /* -------------------------------------------------------------------------- */ Real ElasticEnergyFunctional::computeF() { - const Surface & displacements = bem.getDisplacements(); - const Surface & tractions = bem.getTractions(); + const Surface& displacements = bem.getDisplacements(); + const Surface& tractions = bem.getTractions(); const UInt n = displacements.size(); - const UInt size = n*n; + const UInt size = n * n; Real res = 0; -#pragma omp parallel for reduction(+:res) +#pragma omp parallel for reduction(+ : res) for (UInt i = 0; i < size; ++i) { res += displacements(i) * tractions(i); } return 0.5 * res; } /* -------------------------------------------------------------------------- */ void ElasticEnergyFunctional::computeGradFP() { *this->gradF += bem.getDisplacements(); } /* -------------------------------------------------------------------------- */ void ElasticEnergyFunctional::computeGradFU() { *this->gradF += bem.getTractions(); } - __END_TAMAAS__ diff --git a/src/bem/elastic_energy_functional.hh b/src/bem/elastic_energy_functional.hh index 02c7732..ccb85af 100644 --- a/src/bem/elastic_energy_functional.hh +++ b/src/bem/elastic_energy_functional.hh @@ -1,61 +1,61 @@ /** * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef ELASTIC_ENERGY_FUNCTIONAL_H #define ELASTIC_ENERGY_FUNCTIONAL_H #include "bem_functional.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ // forward declaration of BemFFTBase class BemFFTBase; /// Energy functional for elasto-static normal contact, no adhesion -class ElasticEnergyFunctional : public Functional{ +class ElasticEnergyFunctional : public Functional { public: /// Constructor - explicit ElasticEnergyFunctional(BemFFTBase & bem); + explicit ElasticEnergyFunctional(BemFFTBase& bem); /// Destructor virtual ~ElasticEnergyFunctional(); public: /// Compute value of objective function Real computeF(); /// Compute gradient of objective function (du) void computeGradFU(); /// Compute gradient of objective function (dp) void computeGradFP(); }; __END_TAMAAS__ -#endif // ENERGY_FUNCTIONAL_H +#endif // ENERGY_FUNCTIONAL_H diff --git a/src/bem/exponential_adhesion_functional.cpp b/src/bem/exponential_adhesion_functional.cpp index 242c664..4f73b39 100644 --- a/src/bem/exponential_adhesion_functional.cpp +++ b/src/bem/exponential_adhesion_functional.cpp @@ -1,94 +1,91 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "exponential_adhesion_functional.hh" -#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -ExponentialAdhesionFunctional::ExponentialAdhesionFunctional(BemFFTBase & bem): - Functional(bem), - exponential_term(bem.getSurface().size(), bem.getSurface().getL()), - surface_t(bem.getSurface().size(), bem.getSurface().getL()) -{} +ExponentialAdhesionFunctional::ExponentialAdhesionFunctional(BemFFTBase& bem) + : Functional(bem), + exponential_term(bem.getSurface().size(), bem.getSurface().getL()), + surface_t(bem.getSurface().size(), bem.getSurface().getL()) {} /* -------------------------------------------------------------------------- */ -ExponentialAdhesionFunctional::~ExponentialAdhesionFunctional() -{} +ExponentialAdhesionFunctional::~ExponentialAdhesionFunctional() {} /* -------------------------------------------------------------------------- */ Real ExponentialAdhesionFunctional::computeF() { this->computeExponentialTerm(); return -SurfaceStatistics::computeSum(this->exponential_term); } /* -------------------------------------------------------------------------- */ void ExponentialAdhesionFunctional::computeGradFU() { this->computeExponentialTerm(); Real rho = this->getParameter("rho"); this->exponential_term /= rho; *this->gradF += this->exponential_term; } /* -------------------------------------------------------------------------- */ void ExponentialAdhesionFunctional::computeGradFP() { - SURFACE_FATAL("Adhesion functional (exponential) cannot be differentiated with respect to P"); - + SURFACE_FATAL("Adhesion functional (exponential) cannot be differentiated " + "with respect to P"); } /* -------------------------------------------------------------------------- */ void ExponentialAdhesionFunctional::computeExponentialTerm() { - const Surface & gap = bem.getGap(); + const Surface& gap = bem.getGap(); const UInt n = gap.size(); const UInt size = n * n; Real rho = this->getParameter("rho"); Real surface_energy = this->getParameter("surface_energy"); - if (surface_energy!=0.) { + if (surface_energy != 0.) { #pragma omp parallel for - for (UInt i = 0 ; i < size ; ++i) { - if (gap(i)>=-1.e-8){ - this->exponential_term(i) = surface_energy * exp(- (gap(i)) / rho); + for (UInt i = 0; i < size; ++i) { + if (gap(i) >= -1.e-8) { + this->exponential_term(i) = surface_energy * exp(-(gap(i)) / rho); } } } } __END_TAMAAS__ diff --git a/src/bem/exponential_adhesion_functional.hh b/src/bem/exponential_adhesion_functional.hh index 336cc25..4ee85de 100644 --- a/src/bem/exponential_adhesion_functional.hh +++ b/src/bem/exponential_adhesion_functional.hh @@ -1,68 +1,69 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ #define __EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ -#include "bem_functional.hh" #include "bem_fft_base.hh" +#include "bem_functional.hh" __BEGIN_TAMAAS__ -/// Energy functional (in displacement) that contains the adhesion term from Müser's contest +/// Energy functional (in displacement) that contains the adhesion term from +/// Müser's contest class ExponentialAdhesionFunctional : public Functional { public: /// Constructor - explicit ExponentialAdhesionFunctional(BemFFTBase & bem); + explicit ExponentialAdhesionFunctional(BemFFTBase& bem); /// Destructor virtual ~ExponentialAdhesionFunctional(); public: /// Compute value of objective function virtual Real computeF(); /// Compute gradient of objective function virtual void computeGradFU(); /// Compute gradient of objective function virtual void computeGradFP(); /// Compute the exponential term in functional void computeExponentialTerm(); private: /// Exponential term in functional Surface exponential_term; /// Surface tractions Surface surface_t; }; __END_TAMAAS__ -#endif // __EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ +#endif // __EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ diff --git a/src/bem/maugis_adhesion_functional.cpp b/src/bem/maugis_adhesion_functional.cpp index be2013a..8b51c01 100644 --- a/src/bem/maugis_adhesion_functional.cpp +++ b/src/bem/maugis_adhesion_functional.cpp @@ -1,104 +1,101 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "maugis_adhesion_functional.hh" -#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -MaugisAdhesionFunctional::MaugisAdhesionFunctional(BemFFTBase & bem): - Functional(bem), - term(bem.getSurface().size(), bem.getSurface().getL()), - gterm(bem.getSurface().size(), bem.getSurface().getL()), - surface_t(bem.getSurface().size(), bem.getSurface().getL()) -{} +MaugisAdhesionFunctional::MaugisAdhesionFunctional(BemFFTBase& bem) + : Functional(bem), term(bem.getSurface().size(), bem.getSurface().getL()), + gterm(bem.getSurface().size(), bem.getSurface().getL()), + surface_t(bem.getSurface().size(), bem.getSurface().getL()) {} /* -------------------------------------------------------------------------- */ -MaugisAdhesionFunctional::~MaugisAdhesionFunctional() -{} +MaugisAdhesionFunctional::~MaugisAdhesionFunctional() {} /* -------------------------------------------------------------------------- */ Real MaugisAdhesionFunctional::computeF() { - const Surface & gap = bem.getGap(); - const UInt n = gap.size(); - const UInt size = n * n; + const Surface& gap = bem.getGap(); + const UInt n = gap.size(); + const UInt size = n * n; - Real rho = this->getParameter("rho"); - Real surface_energy = this->getParameter("surface_energy"); + Real rho = this->getParameter("rho"); + Real surface_energy = this->getParameter("surface_energy"); - if (surface_energy!=0.) { - #pragma omp parallel for + if (surface_energy != 0.) { +#pragma omp parallel for - for (UInt i = 0 ; i < size ; ++i) { - if (rho>=gap(i)){ - this->term(i) = surface_energy *(1-gap(i)/rho); - } + for (UInt i = 0; i < size; ++i) { + if (rho >= gap(i)) { + this->term(i) = surface_energy * (1 - gap(i) / rho); } } + } return -SurfaceStatistics::computeSum(this->term); } /* -------------------------------------------------------------------------- */ void MaugisAdhesionFunctional::computeGradFU() { - const Surface & gap = bem.getGap(); - const UInt n = gap.size(); - const UInt size = n * n; + const Surface& gap = bem.getGap(); + const UInt n = gap.size(); + const UInt size = n * n; - Real rho = this->getParameter("rho"); - Real surface_energy = this->getParameter("surface_energy"); + Real rho = this->getParameter("rho"); + Real surface_energy = this->getParameter("surface_energy"); - if (surface_energy!=0.) { - #pragma omp parallel for + if (surface_energy != 0.) { +#pragma omp parallel for - for (UInt i = 0 ; i < size ; ++i) { - if (rho>=gap(i)){ - this->gterm(i) = surface_energy /rho; - } - else {this->gterm(i) =0;} + for (UInt i = 0; i < size; ++i) { + if (rho >= gap(i)) { + this->gterm(i) = surface_energy / rho; + } else { + this->gterm(i) = 0; } } + } *this->gradF += this->gterm; } /* -------------------------------------------------------------------------- */ void MaugisAdhesionFunctional::computeGradFP() { - SURFACE_FATAL("Adhesion functional (Maugis) cannot be differentiated with respect to P"); - + SURFACE_FATAL("Adhesion functional (Maugis) cannot be differentiated with " + "respect to P"); } __END_TAMAAS__ diff --git a/src/bem/maugis_adhesion_functional.hh b/src/bem/maugis_adhesion_functional.hh index 2ca97d5..b229bb3 100644 --- a/src/bem/maugis_adhesion_functional.hh +++ b/src/bem/maugis_adhesion_functional.hh @@ -1,70 +1,69 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __MAUGIS_ADHESION_FUNCTIONAL_HH__ #define __MAUGIS_ADHESION_FUNCTIONAL_HH__ -#include "bem_functional.hh" #include "bem_fft_base.hh" +#include "bem_functional.hh" __BEGIN_TAMAAS__ -/// Energy functional (in displacement) that contains the adhesion term from Maugis model +/// Energy functional (in displacement) that contains the adhesion term from +/// Maugis model class MaugisAdhesionFunctional : public Functional { public: /// Constructor - explicit MaugisAdhesionFunctional(BemFFTBase & bem); + explicit MaugisAdhesionFunctional(BemFFTBase& bem); /// Destructor virtual ~MaugisAdhesionFunctional(); public: /// Compute value of objective function virtual Real computeF(); /// Compute gradient of objective function virtual void computeGradFU(); /// Compute gradient of objective function virtual void computeGradFP(); - - private: /// term in functional Surface term; /// term in derivative functional Surface gterm; /// Surface tractions Surface surface_t; }; __END_TAMAAS__ -#endif // __MAUGIS_ADHESION_FUNCTIONAL_HH__ +#endif // __MAUGIS_ADHESION_FUNCTIONAL_HH__ diff --git a/src/bem/squared_exponential_adhesion_functional.cpp b/src/bem/squared_exponential_adhesion_functional.cpp index 7f70819..9a3852a 100644 --- a/src/bem/squared_exponential_adhesion_functional.cpp +++ b/src/bem/squared_exponential_adhesion_functional.cpp @@ -1,93 +1,91 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "squared_exponential_adhesion_functional.hh" -#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -SquaredExponentialAdhesionFunctional::SquaredExponentialAdhesionFunctional(BemFFTBase & bem): - Functional(bem), - exponential_term(bem.getSurface().size(), bem.getSurface().getL()), - surface_t(bem.getSurface().size(), bem.getSurface().getL()) -{} +SquaredExponentialAdhesionFunctional::SquaredExponentialAdhesionFunctional( + BemFFTBase& bem) + : Functional(bem), + exponential_term(bem.getSurface().size(), bem.getSurface().getL()), + surface_t(bem.getSurface().size(), bem.getSurface().getL()) {} /* -------------------------------------------------------------------------- */ -SquaredExponentialAdhesionFunctional::~SquaredExponentialAdhesionFunctional() -{} +SquaredExponentialAdhesionFunctional::~SquaredExponentialAdhesionFunctional() {} /* -------------------------------------------------------------------------- */ Real SquaredExponentialAdhesionFunctional::computeF() { this->computeExponentialTerm(); return -SurfaceStatistics::computeSum(this->exponential_term); } /* -------------------------------------------------------------------------- */ void SquaredExponentialAdhesionFunctional::computeGradFU() { this->computeExponentialTerm(); - - *this->gradF += this->exponential_term; } /* -------------------------------------------------------------------------- */ void SquaredExponentialAdhesionFunctional::computeGradFP() { - SURFACE_FATAL("Adhesion functional (exponential) cannot be differentiated with respect to P"); - + SURFACE_FATAL("Adhesion functional (exponential) cannot be differentiated " + "with respect to P"); } /* -------------------------------------------------------------------------- */ void SquaredExponentialAdhesionFunctional::computeExponentialTerm() { - const Surface & gap = bem.getGap(); + const Surface& gap = bem.getGap(); const UInt n = gap.size(); const UInt size = n * n; Real rho = this->getParameter("rho"); Real surface_energy = this->getParameter("surface_energy"); - if (surface_energy!=0.) { + if (surface_energy != 0.) { #pragma omp parallel for - for (UInt i = 0 ; i < size ; ++i) { - if (gap(i)>=-1.e-8){ - this->exponential_term(i) = (gap(i))* surface_energy * exp(- (gap(i))*(gap(i)) / 2*rho*rho) / (rho*rho); + for (UInt i = 0; i < size; ++i) { + if (gap(i) >= -1.e-8) { + this->exponential_term(i) = (gap(i)) * surface_energy * + exp(-(gap(i)) * (gap(i)) / 2 * rho * rho) / + (rho * rho); } } } } __END_TAMAAS__ diff --git a/src/bem/squared_exponential_adhesion_functional.hh b/src/bem/squared_exponential_adhesion_functional.hh index 29b460f..69e0b0b 100644 --- a/src/bem/squared_exponential_adhesion_functional.hh +++ b/src/bem/squared_exponential_adhesion_functional.hh @@ -1,68 +1,69 @@ /** * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __SQUARED_EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ #define __SQUARED_EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ -#include "bem_functional.hh" #include "bem_fft_base.hh" +#include "bem_functional.hh" __BEGIN_TAMAAS__ -/// Energy functional (in displacement) that contains the adhesion term with quadratic gap +/// Energy functional (in displacement) that contains the adhesion term with +/// quadratic gap class SquaredExponentialAdhesionFunctional : public Functional { public: /// Constructor - explicit SquaredExponentialAdhesionFunctional(BemFFTBase & bem); + explicit SquaredExponentialAdhesionFunctional(BemFFTBase& bem); /// Destructor virtual ~SquaredExponentialAdhesionFunctional(); public: /// Compute value of objective function virtual Real computeF(); /// Compute gradient of objective function virtual void computeGradFU(); /// Compute gradient of objective function virtual void computeGradFP(); /// Compute the exponential term in functional void computeExponentialTerm(); private: /// Exponential term in functional Surface exponential_term; /// Surface tractions Surface surface_t; }; __END_TAMAAS__ -#endif // __SQUARED_EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ +#endif // __SQUARED_EXPONENTIAL_ADHESION_FUNCTIONAL_HH__ diff --git a/src/core/array.hh b/src/core/array.hh index 875e2c9..56d43eb 100644 --- a/src/core/array.hh +++ b/src/core/array.hh @@ -1,163 +1,163 @@ /** + * @file * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __ARRAY__HH__ #define __ARRAY__HH__ /* -------------------------------------------------------------------------- */ #include "tamaas.hh" +#include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ +/** + * @brief Generic storage class with wrapping capacities + */ template class Array { public: - /// Trivial constructor + /// Default Array() = default; /// Empty array of given size - Array(UInt size): - Array() { - this->resize(size); - } + Array(UInt size) : Array() { this->resize(size); } /// Copy constructor (deep) - Array(const Array & v): - Array() { + Array(const Array& v) : Array() { this->resize(v._size); - std::copy(v._data, v._data+v._size, this->_data); + std::copy(v._data, v._data + v._size, this->_data); } /// Move constructor (transfers data ownership) - Array(Array&& v): - Array() { + Array(Array&& v) : Array() { _data = std::exchange(v._data, nullptr); _size = std::exchange(v._size, 0); wrapped = std::exchange(v.wrapped, false); } /// Wrap array on data - Array(T * data, UInt size): - Array() { - this->wrapMemory(data, size); - } + Array(T* data, UInt size) : Array() { this->wrapMemory(data, size); } /// Destructor - virtual ~Array(){ - if (wrapped == false){ - delete [] _data; - } + virtual ~Array() { + if (wrapped == false) + _alloc.deallocate(_data, _size); } public: /// Copy operator - Array & operator=(const Array & v){ + Array& operator=(const Array& v) { this->wrapped = false; - if (v.size() != this->size()) this->resize(v.size()); + if (v.size() != this->size()) + this->resize(v.size()); #pragma omp parallel for - for (UInt i = 0 ; i < this->_size ; ++i) { + for (UInt i = 0; i < this->_size; ++i) { _data[i] = v._data[i]; } return *this; } /// Move operator - Array & operator=(Array && v) { + Array& operator=(Array&& v) { if (this != &v) { - if (!wrapped) delete[] _data; + if (!wrapped) + _alloc.deallocate(_data, _size); _data = v._data; _size = v._size; wrapped = v.wrapped; v._data = nullptr; v._size = 0; v.wrapped = false; } return *this; } /// Wrap a memory pointer - void wrapMemory(T * data, UInt size) { + void wrapMemory(T* data, UInt size) { this->_data = data; this->_size = size; this->wrapped = true; } /// Assign a sigle value to the array - void assign(UInt size, const T & value){ + void assign(UInt size, const T& value) { this->resize(size); #pragma omp parallel for for (UInt i = 0; i < size; i++) { _data[i] = value; } } void setWrapped(bool w) { wrapped = w; } /// Data pointer access (const) - const T * data() const{ return _data; } + const T* data() const { return _data; } /// Data pointer access (non-const) - T * data() { return _data; } + T* data() { return _data; } /// Data pointer setter - void setData(T * new_ptr) { _data = new_ptr;} + void setData(T* new_ptr) { _data = new_ptr; } /// Resize array - void resize(UInt size){ + void resize(UInt size) { if (wrapped == true) TAMAAS_EXCEPTION("cannot resize wrapped array"); // Erase array if (size == 0) { - delete [] this->_data; + _alloc.deallocate(_data, _size); this->_data = nullptr; this->_size = 0; return; } // Do nothing - if (size == this->_size) return; + if (size == this->_size) + return; // Allocate new data - delete [] _data; + _alloc.deallocate(_data, _size); - this->_data = new T[size]; + this->_data = _alloc.allocate(size); this->_size = size; } /// Access operator - inline T & operator[] (UInt i) { + inline T& operator[](UInt i) { TAMAAS_ASSERT(i < _size, "memory overflow"); return _data[i]; } /// Access operator (const) - inline const T & operator[] (UInt i) const { + inline const T& operator[](UInt i) const { TAMAAS_ASSERT(i < _size, "memory overflow"); return _data[i]; } /// Get size of array - inline UInt size() const {return _size;} + inline UInt size() const { return _size; } private: - T * _data = nullptr; + T* _data = nullptr; UInt _size = 0; bool wrapped = false; + DEFAULT_ALLOCATOR _alloc = DEFAULT_ALLOCATOR(); }; __END_TAMAAS__ /* -------------------------------------------------------------------------- */ #endif /* __ARRAY__HH__ */ diff --git a/src/core/fft_plan_manager.cpp b/src/core/fft_plan_manager.cpp index 93f9d0d..d01d4c9 100644 --- a/src/core/fft_plan_manager.cpp +++ b/src/core/fft_plan_manager.cpp @@ -1,107 +1,102 @@ /** + * @file * * @author Guillaume Anciaux * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "fft_plan_manager.hh" #include "fftransform_fftw.hh" #if defined(USE_CUFFT) #include "fftransform_cufft.hh" #endif /* -------------------------------------------------------------------------- */ - __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -FFTPlanManager::FFTPlanManager(){ -} +FFTPlanManager::FFTPlanManager() {} /* -------------------------------------------------------------------------- */ -FFTPlanManager::~FFTPlanManager(){ - clean(); -} +FFTPlanManager::~FFTPlanManager() { clean(); } /* -------------------------------------------------------------------------- */ -FFTPlanManager & FFTPlanManager::get(){ +FFTPlanManager& FFTPlanManager::get() { if (FFTPlanManager::singleton == NULL) FFTPlanManager::singleton = new FFTPlanManager(); return *FFTPlanManager::singleton; } /* -------------------------------------------------------------------------- */ void FFTPlanManager::clean() { auto it = plans.begin(); auto end = plans.end(); - for (; it != end ; ++it) { + for (; it != end; ++it) { delete std::get<0>(it->second); delete std::get<1>(it->second); delete std::get<2>(it->second); plans.erase(it->first); } } /* -------------------------------------------------------------------------- */ -template<> -void FFTPlanManager::destroyPlan(const Real * some) { +template <> +void FFTPlanManager::destroyPlan(const Real* some) { auto it = plans.begin(); auto end = plans.end(); - for (; it != end ; ++it) { + for (; it != end; ++it) { if (it->first.first == some) { delete std::get<0>(it->second); delete std::get<1>(it->second); delete std::get<2>(it->second); plans.erase(it->first); } } } /* -------------------------------------------------------------------------- */ -template<> -void FFTPlanManager::destroyPlan(const Complex * some) { +template <> +void FFTPlanManager::destroyPlan(const Complex* some) { auto it = plans.begin(); auto end = plans.end(); - for (; it != end ; ++it) { + for (; it != end; ++it) { if (it->first.second == some) { delete std::get<0>(it->second); delete std::get<1>(it->second); delete std::get<2>(it->second); plans.erase(it->first); } } } /* -------------------------------------------------------------------------- */ -FFTPlanManager * FFTPlanManager::singleton = NULL; +FFTPlanManager* FFTPlanManager::singleton = NULL; /* -------------------------------------------------------------------------- */ - - __END_TAMAAS__ diff --git a/src/core/fft_plan_manager.hh b/src/core/fft_plan_manager.hh index 4c3d2bd..a0b1263 100644 --- a/src/core/fft_plan_manager.hh +++ b/src/core/fft_plan_manager.hh @@ -1,132 +1,139 @@ /** + * @file * * @author Guillaume Anciaux * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef FFT_PLAN_MANAGER_H #define FFT_PLAN_MANAGER_H /* -------------------------------------------------------------------------- */ -#include #include "fftransform.hh" #include "fftransform_fftw.hh" -#if (USE_CUFFT) +#include +#ifdef USE_CUDA #include "fftransform_cufft.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ +/** + * @brief Singleton class for FFT plan management + */ class FFTPlanManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: FFTPlanManager(); public: virtual ~FFTPlanManager(); public: /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ /// Get singleton instance - static FFTPlanManager & get(); + static FFTPlanManager& get(); /// Create/retrieve a plan from two surfaces template - FFTransform & createPlan(Grid & input, GridHermitian & output); + FFTransform& createPlan(Grid& input, + GridHermitian& output); /// Remove all plans void clean(); /// Destroy a plan from two surfaces template - void destroyPlan(Grid & input, GridHermitian & output); + void destroyPlan(Grid& input, GridHermitian& output); /// Destroy any plan containing a given data pointer - template - void destroyPlan(const T * some); + template + void destroyPlan(const T* some); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: - typedef std::map, - std::tuple *, - FFTransform *, - FFTransform *> - > FFTMap; + using FFTMap = + std::map, + std::tuple*, FFTransform*, + FFTransform*>>; FFTMap plans; - static FFTPlanManager * singleton; + static FFTPlanManager* singleton; }; /* -------------------------------------------------------------------------- */ -template -FFTransform & FFTPlanManager::createPlan(Grid & input, - GridHermitian & output){ +template +FFTransform& +FFTPlanManager::createPlan(Grid& input, + GridHermitian& output) { static_assert(dim <= 3, "Cannot do FFT of dimension higher than 3"); auto index = std::make_pair(const_cast(input.getInternalData()), const_cast(output.getInternalData())); auto it = plans.find(index); auto end = plans.end(); if (it == end) { -#if defined(USE_CUFFT) - std::get(plans[index]) = new FFTransformCUFFT(input.size(),input,output); +#ifdef USE_CUDA + std::get(plans[index]) = + new FFTransformCUFFT(input, output); // TODO cuda #else - std::get(plans[index]) = new FFTransformFFTW(input,output); + std::get(plans[index]) = + new FFTransformFFTW(input, output); #endif } - return *std::get(plans[index]); + return *std::get(plans[index]); } /* -------------------------------------------------------------------------- */ -template -void FFTPlanManager::destroyPlan(Grid & input, - GridHermitian & output){ +template +void FFTPlanManager::destroyPlan(Grid& input, + GridHermitian& output) { auto index = std::make_pair(const_cast(input.getInternalData()), - const_cast(output.getInternalData())); + const_cast(output.getInternalData())); auto it = plans.find(index); auto end = plans.end(); - if (it != end){ + if (it != end) { delete std::get(plans[index]); plans.erase(index); } } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ /* -------------------------------------------------------------------------- */ #endif /* FFT_PLAN_MANAGER_H */ diff --git a/src/core/fftransform.cpp b/src/core/fftransform.cpp index ca4ed2e..7718a14 100644 --- a/src/core/fftransform.cpp +++ b/src/core/fftransform.cpp @@ -1,57 +1,56 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "fftransform.hh" __BEGIN_TAMAAS__ -template -FFTransform::FFTransform(Grid & real, - GridHermitian & spectral): - real(real), - spectral(spectral) -{} +template +FFTransform::FFTransform(Grid& real, + GridHermitian& spectral) + : real(real), spectral(spectral) {} /* -------------------------------------------------------------------------- */ -template +template FFTransform::~FFTransform() {} /* -------------------------------------------------------------------------- */ -template +template void FFTransform::normalize() { - real /= (Real) real.getNbPoints(); + real /= (Real)real.getNbPoints(); } /* -------------------------------------------------------------------------- */ template class FFTransform; template class FFTransform; template class FFTransform; __END_TAMAAS__ diff --git a/src/core/fftransform.hh b/src/core/fftransform.hh index f294407..dfd2ba4 100644 --- a/src/core/fftransform.hh +++ b/src/core/fftransform.hh @@ -1,119 +1,121 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef FFTRANSFORM_HH #define FFTRANSFORM_HH /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "grid.hh" #include "grid_hermitian.hh" +#include "tamaas.hh" #include "types.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ +/** + * @brief Generic class for FFT interface wrapping + */ template class FFTransform { public: /// Constructor - FFTransform(Grid & real, - GridHermitian & spectral); + FFTransform(Grid& real, GridHermitian& spectral); /// Destructor virtual ~FFTransform(); public: /// Perform FFT virtual void forwardTransform() = 0; /// Perform IFFT virtual void backwardTransform() = 0; /// Normalize the real surface after backward transform virtual void normalize(); public: /// Fill a grid with modevectors: boolean if grid has hermitian dimensions template - static Grid computeFrequencies(const std::array & sizes); + static Grid computeFrequencies(const std::array& sizes); protected: - Grid & real; - GridHermitian & spectral; + Grid& real; + GridHermitian& spectral; }; /* -------------------------------------------------------------------------- */ -template -template +template +template Grid -FFTransform::computeFrequencies(const std::array & sizes) { +FFTransform::computeFrequencies(const std::array& sizes) { // If hermitian is true, we suppose the dimensions of freq are // reduced based on hermitian symetry and that it has dim components - auto & n = sizes; + auto& n = sizes; Grid freq(n, dim); - std::array tuple = {0}; + std::array tuple{{0}}; #pragma omp parallel for firstprivate(tuple) - for (auto it = freq.begin(dim) ; it < freq.end(dim) ; ++it) { + for (auto it = freq.begin(dim); it < freq.end(dim); ++it) { VectorProxy wavevector(&(*it), dim); UInt index = freq.getNbPoints() - (freq.end(dim) - it); /// Computing tuple from index - for (UInt d = dim-1 ; d > 0 ; d--) { + for (UInt d = dim - 1; d > 0; d--) { tuple[d] = index % n[d]; index -= tuple[d]; index /= n[d]; } tuple[0] = index; UInt dmax = dim; if (hermitian) { dmax = dim - 1; - wavevector(dim-1) = tuple[dim-1]; + wavevector(dim - 1) = tuple[dim - 1]; } - for (UInt d = 0 ; d < dmax ; d++) { + for (UInt d = 0; d < dmax; d++) { T td = tuple[d]; T nd = n[d]; - T q = (tuple[d] <= n[d]/2) ? td : td-nd; + T q = (tuple[d] <= n[d] / 2) ? td : td - nd; wavevector(d) = q; } - } return freq; } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ /* -------------------------------------------------------------------------- */ -#endif // FFTRANSFORM_HH +#endif // FFTRANSFORM_HH diff --git a/src/core/fftransform_fftw.cpp b/src/core/fftransform_fftw.cpp index 14d1641..f864573 100644 --- a/src/core/fftransform_fftw.cpp +++ b/src/core/fftransform_fftw.cpp @@ -1,99 +1,93 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "fftransform_fftw.hh" __BEGIN_TAMAAS__ -template -FFTransformFFTW::FFTransformFFTW(Grid & real, - GridHermitian & spectral): - FFTransform(real, spectral), - forward_plan(NULL), - backward_plan(NULL) -{ +template +FFTransformFFTW::FFTransformFFTW(Grid& real, + GridHermitian& spectral) + : FFTransform(real, spectral), forward_plan(NULL), + backward_plan(NULL) { TAMAAS_ASSERT(real.getNbComponents() == spectral.getNbComponents(), - "components for FFTW do not match"); + "components for FFTW do not match"); // Data pointers - Real * in = this->real.getInternalData(); - fftw_complex * out = reinterpret_cast(this->spectral.getInternalData()); + Real* in = this->real.getInternalData(); + fftw_complex* out = + reinterpret_cast(this->spectral.getInternalData()); int components = real.getNbComponents(); // fftw parameters - int rank = dim; // dimension of fft + int rank = dim; // dimension of fft int n[dim] = {0}; - std::copy(real.sizes().begin(), real.sizes().end(), n); // size of individual fft - int howmany = components; // how many fft to compute - int idist = 1, odist = 1; // components are next to each other in memory + std::copy(real.sizes().begin(), real.sizes().end(), + n); // size of individual fft + int howmany = components; // how many fft to compute + int idist = 1, odist = 1; // components are next to each other in memory int istride = components, ostride = components; - int * inembeded = NULL, * onembeded = NULL; // row major - - - forward_plan = fftw_plan_many_dft_r2c(rank, n, howmany, - in, inembeded, - istride, idist, - out, onembeded, - ostride, odist, - FFTW_ESTIMATE); - backward_plan = fftw_plan_many_dft_c2r(rank, n, howmany, - out, onembeded, - ostride, odist, - in, inembeded, - istride, idist, - FFTW_ESTIMATE); + int *inembed = NULL, *onembed = NULL; // row major + + forward_plan = + fftw_plan_many_dft_r2c(rank, n, howmany, in, inembed, istride, idist, out, + onembed, ostride, odist, FFTW_ESTIMATE); + backward_plan = + fftw_plan_many_dft_c2r(rank, n, howmany, out, onembed, ostride, odist, in, + inembed, istride, idist, FFTW_ESTIMATE); } /* -------------------------------------------------------------------------- */ -template +template FFTransformFFTW::~FFTransformFFTW() { fftw_destroy_plan(forward_plan); fftw_destroy_plan(backward_plan); } /* -------------------------------------------------------------------------- */ -template +template void FFTransformFFTW::forwardTransform() { fftw_execute(forward_plan); } /* -------------------------------------------------------------------------- */ -template +template void FFTransformFFTW::backwardTransform() { fftw_execute(backward_plan); this->normalize(); } /* -------------------------------------------------------------------------- */ template class FFTransformFFTW; template class FFTransformFFTW; template class FFTransformFFTW; __END_TAMAAS__ diff --git a/src/core/fftransform_fftw.hh b/src/core/fftransform_fftw.hh index 3a91da8..3a0a2a3 100644 --- a/src/core/fftransform_fftw.hh +++ b/src/core/fftransform_fftw.hh @@ -1,60 +1,63 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef FFTRANSFORM_FFTW_HH #define FFTRANSFORM_FFTW_HH #include "fftransform.hh" #include __BEGIN_TAMAAS__ +/** + * @brief Class wrapping fftw's interface + */ template class FFTransformFFTW : public FFTransform { public: /// Constructor - FFTransformFFTW(Grid & real, - GridHermitian & spectral); + FFTransformFFTW(Grid& real, GridHermitian& spectral); /// Destructor virtual ~FFTransformFFTW(); public: /// Perform FFT void forwardTransform() override; /// Perform IFFT void backwardTransform() override; private: fftw_plan forward_plan; fftw_plan backward_plan; }; __END_TAMAAS__ -#endif // FFTRANSFORM_FFTW_HH +#endif // FFTRANSFORM_FFTW_HH diff --git a/src/core/tamaas.cpp b/src/core/fftw_allocator.hh similarity index 62% copy from src/core/tamaas.cpp copy to src/core/fftw_allocator.hh index d4aa8ac..66416e3 100644 --- a/src/core/tamaas.cpp +++ b/src/core/fftw_allocator.hh @@ -1,50 +1,54 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * - * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de + * Copyright (©) 2017 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ - +#ifndef __FFTW_ALLOCATOR_HH__ +#define __FFTW_ALLOCATOR_HH__ +/* -------------------------------------------------------------------------- */ #include -#include -#include "tamaas.hh" -#include "fft_plan_manager.hh" - +#include /* -------------------------------------------------------------------------- */ -__BEGIN_TAMAAS__ +namespace tamaas { -void initialize(UInt num_threads) { - fftw_init_threads(); +/// Class allocating +/// [SIMD](http://www.fftw.org/fftw3_doc/SIMD-alignment-and-fftw_005fmalloc.html#SIMD-alignment-and-fftw_005fmalloc) +/// aligned memory +template +struct FFTWAllocator { + /// Allocate memory + T* allocate(std::size_t n) { + T* p = nullptr; + p = (T*)fftw_malloc(sizeof(T) * n); + return p; + } - if (num_threads) omp_set_num_threads(num_threads); - fftw_plan_with_nthreads(omp_get_max_threads()); -} - -/* -------------------------------------------------------------------------- */ + /// Free memory + void deallocate(T* p, __attribute__((unused)) std::size_t n) { fftw_free(p); } +}; -void finalize() { - FFTPlanManager::get().clean(); - fftw_cleanup_threads(); -} +} // namespace tamaas -__END_TAMAAS__ +#endif // __FFTW_ALLOCATOR_HH__ diff --git a/src/core/grid.cpp b/src/core/grid.cpp index 617a0df..b6e815d 100644 --- a/src/core/grid.cpp +++ b/src/core/grid.cpp @@ -1,134 +1,124 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "grid.hh" -#include -#include +#include "tamaas.hh" #include +#include +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ template -Grid::Grid(): - GridBase() { +Grid::Grid() : GridBase() { this->n.fill(0); this->strides.fill(1); this->nb_components = 1; } /* -------------------------------------------------------------------------- */ template -Grid::Grid(const std::array & n, - UInt nb_components): - GridBase() { +Grid::Grid(const std::array& n, UInt nb_components) + : GridBase() { this->init(n, nb_components); } template -Grid::Grid(const std::vector & n, - UInt nb_components): - GridBase() { +Grid::Grid(const std::vector& n, UInt nb_components) + : GridBase() { if (n.size() != dim) TAMAAS_EXCEPTION("Provided sizes for grid do not match dimension"); this->init(n, nb_components); } template -Grid::Grid(const std::initializer_list & n, - UInt nb_components): - GridBase() { +Grid::Grid(const std::initializer_list& n, UInt nb_components) + : GridBase() { if (n.size() != dim) TAMAAS_EXCEPTION("Provided sizes for grid do not match dimension"); this->init(n, nb_components); } template -Grid::Grid(const Grid & o): - GridBase(o), - n(o.n), - strides(o.strides) -{} - +Grid::Grid(const Grid& o) + : GridBase(o), n(o.n), strides(o.strides) {} template -Grid::Grid(Grid&& o): - GridBase(o), - n(std::move(o.n)), - strides(std::move(o.strides)) -{} +Grid::Grid(Grid&& o) + : GridBase(o), n(std::move(o.n)), strides(std::move(o.strides)) {} /* -------------------------------------------------------------------------- */ template -void Grid::resize(const std::array & n) { +void Grid::resize(const std::array& n) { this->n = n; UInt size = this->computeSize(); this->data.resize(size); this->data.assign(size, T(0.)); this->computeStrides(); } /* -------------------------------------------------------------------------- */ template void Grid::computeStrides() { - std::copy(n.begin()+1, n.end(), strides.rbegin()+2); + std::copy(n.begin() + 1, n.end(), strides.rbegin() + 2); strides[dim] = 1; - strides[dim-1] = this->nb_components; - std::partial_sum(strides.rbegin(), strides.rend(), - strides.rbegin(), std::multiplies()); - + strides[dim - 1] = this->nb_components; + std::partial_sum(strides.rbegin(), strides.rend(), strides.rbegin(), + std::multiplies()); } /* -------------------------------------------------------------------------- */ template -void Grid::printself(std::ostream & str) const { +void Grid::printself(std::ostream& str) const { str << "Grid(" << dim << ", " << this->nb_components << ") {"; - for (auto & val : *this) { + for (auto& val : *this) { str << val << ", "; } str << "\b\b}"; } /* -------------------------------------------------------------------------- */ /// Class instanciation -#define GRID_INSTANCIATE_TYPE(type) template class Grid; \ - template class Grid; \ +#define GRID_INSTANCIATE_TYPE(type) \ + template class Grid; \ + template class Grid; \ template class Grid GRID_INSTANCIATE_TYPE(Real); GRID_INSTANCIATE_TYPE(UInt); GRID_INSTANCIATE_TYPE(Complex); GRID_INSTANCIATE_TYPE(int); GRID_INSTANCIATE_TYPE(bool); GRID_INSTANCIATE_TYPE(unsigned long); #undef GRID_INSTANCIATE_TYPE __END_TAMAAS__ diff --git a/src/core/grid.hh b/src/core/grid.hh index 0893cc3..153f00c 100644 --- a/src/core/grid.hh +++ b/src/core/grid.hh @@ -1,196 +1,194 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_HH__ #define __GRID_HH__ /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "grid_base.hh" +#include "tamaas.hh" #include -#include #include #include +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /** * @brief Multi-dimensional & multi-component array class * * This class is a container for multi-component data stored on a multi- * dimensional grid. * * The access function is the parenthesis operator. For a grid of dimension d, * the operator takes d+1 arguments: the first d arguments are the position on * the grid and the last one is the component of the stored data. * * It is also possible to use the access operator with only one argument, it is * then considering the grid as a flat array, accessing the given cell of the * array. */ template -class Grid: public GridBase { +class Grid : public GridBase { public: -/* -------------------------------------------------------------------------- */ -/* Types */ -/* -------------------------------------------------------------------------- */ - typedef T value_type; + /* ------------------------------------------------------------------------ */ + /* Types */ + /* ------------------------------------------------------------------------ */ + using value_type = T; static constexpr UInt dimension = dim; -/* -------------------------------------------------------------------------- */ -/* Constructors */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Constructors */ + /* ------------------------------------------------------------------------ */ public: /// Constructor by default (empty array) Grid(); /// Constructor - Grid(const std::array & n, - UInt nb_components); + Grid(const std::array& n, UInt nb_components); /// Constructor with vectors - Grid(const std::vector & n, - UInt nb_components); + Grid(const std::vector& n, UInt nb_components); /// Constructor with initializer list - Grid(const std::initializer_list & n, - UInt nb_components); + Grid(const std::initializer_list& n, UInt nb_components); /// Copy constructor - Grid(const Grid & o); + Grid(const Grid& o); /// Move constructor (transfers data ownership) Grid(Grid&& o); private: /// Init from standard container template - void init(const Container & n, UInt nb_components); + void init(const Container& n, UInt nb_components); public: -/* -------------------------------------------------------------------------- */ -/* Common operations */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Common operations */ + /* ------------------------------------------------------------------------ */ /// Resize array - void resize(const std::array & n); + void resize(const std::array& n); /// Compute size inline UInt computeSize() const override; /// Compute strides virtual void computeStrides(); /// Print - virtual void printself(std::ostream & str) const; + virtual void printself(std::ostream& str) const; /// Get sizes - const std::array & sizes() const {return n;} + const std::array& sizes() const { return n; } /// Get strides - const std::array & getStrides() const {return this->strides;} + const std::array& getStrides() const { return this->strides; } -/* -------------------------------------------------------------------------- */ -/* Access operators */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Access operators */ + /* ------------------------------------------------------------------------ */ /// Variadic access operator (non-const) template - inline T & operator()(T1... args); + inline T& operator()(T1... args); /// Variadic access operator template - inline const T & operator()(T1... args) const; + inline const T& operator()(T1... args) const; /// Tuple index access operator - inline T & operator()(std::array tuple); - inline const T & operator()(std::array tuple) const; + inline T& operator()(std::array tuple); + inline const T& operator()(std::array tuple) const; private: /// Unpacking the arguments of variadic () template - inline UInt unpackOffset(UInt offset, UInt index_pos, - UInt index, T1... rest) const; + inline UInt unpackOffset(UInt offset, UInt index_pos, UInt index, + T1... rest) const; /// End case for recursion template - inline UInt unpackOffset(UInt offset, UInt index_pos, - UInt index) const; + inline UInt unpackOffset(UInt offset, UInt index_pos, UInt index) const; /// Computing offset for a tuple index - inline UInt computeOffset(std::array tuple) const; + inline UInt computeOffset(std::array tuple) const; -/* -------------------------------------------------------------------------- */ -/* Move/Copy operators */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Move/Copy operators */ + /* ------------------------------------------------------------------------ */ public: // = operator - Grid & operator=(const Grid & other); + Grid& operator=(const Grid& other); // = operator (not const input, otherwise gcc is confused) - Grid & operator=(Grid & other); + Grid& operator=(Grid& other); // = operator (move) - Grid & operator=(Grid && other); + Grid& operator=(Grid&& other); // = operator for scalar - Grid & operator=(T val) { GridBase::operator=(val); return *this; } + Grid& operator=(T val) { + GridBase::operator=(val); + return *this; + } // Copy data from another grid template - void copy(const Grid & other); + void copy(const Grid& other); // Move data from another grid template - void move(Grid && other); + void move(Grid&& other); -/* -------------------------------------------------------------------------- */ -/* Iterators */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Iterators */ + /* ------------------------------------------------------------------------ */ public: using iterator = typename GridBase::iterator; using const_iterator = typename GridBase::const_iterator; public: iterator begin(UInt n = 1) override { - return iterator(this->getInternalData()+this->offset, 0, n); + return iterator(this->getInternalData() + this->offset, 0, n); } iterator end(UInt n = 1) override { - return iterator(this->getInternalData()+this->offset, - this->dataSize(), n); + return iterator(this->getInternalData() + this->offset, this->dataSize(), + n); } const_iterator begin(UInt n = 1) const override { - return const_iterator(this->getInternalData()+this->offset, 0, n); + return const_iterator(this->getInternalData() + this->offset, 0, n); } const_iterator end(UInt n = 1) const override { - return const_iterator(this->getInternalData()+this->offset, - this->dataSize(), n); + return const_iterator(this->getInternalData() + this->offset, + this->dataSize(), n); } -/* -------------------------------------------------------------------------- */ -/* Member variables */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Member variables */ + /* ------------------------------------------------------------------------ */ protected: - std::array n; - std::array strides; + std::array n; ///< shape of grid: size per dimension + std::array strides; ///< strides for access }; __END_TAMAAS__ - /* -------------------------------------------------------------------------- */ /* Inline/template function definitions */ /* -------------------------------------------------------------------------- */ #include "grid_tmpl.hh" /* -------------------------------------------------------------------------- */ - -#endif // __GRID_HH__ +#endif // __GRID_HH__ diff --git a/src/core/grid_base.hh b/src/core/grid_base.hh index ce2cfaf..52ed98d 100644 --- a/src/core/grid_base.hh +++ b/src/core/grid_base.hh @@ -1,318 +1,290 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_BASE_HH__ #define __GRID_BASE_HH__ /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "array.hh" #include "iterator.hh" +#include "loop.hh" +#include "tamaas.hh" #include +#include #include #include -#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /// Namespace for view index classes namespace view { - /// Index class - struct index { - index(Int i = -1):i(i){} - Int i; - }; - - /// Blocked index class - struct blocked : public index { - blocked(Int i):index(i){} - }; - - /// Free index class - struct free : public index { - free():index(-1){} - }; -} +/// Index class +struct index { + index(Int i = -1) : i(i) {} + Int i; +}; + +/// Blocked index class +struct blocked : public index { + blocked(Int i) : index(i) {} +}; + +/// Free index class +struct free : public index { + free() : index(-1) {} +}; +} // namespace view +/** + * @brief Dimension agnostic grid with components stored per points + */ template class GridBase { public: /// Constructor by default GridBase() = default; /// Copy constructor - GridBase(const GridBase & o): data(o.data), - nb_components(o.nb_components), - offset(o.offset) {} + GridBase(const GridBase& o) + : data(o.data), nb_components(o.nb_components), offset(o.offset) {} /// Move constructor (transfers data ownership) - GridBase(GridBase&& o): data(std::move(o.data)), - nb_components(std::exchange(o.nb_components, 1)), - offset(std::exchange(o.offset, 0)) {} + GridBase(GridBase&& o) + : data(std::move(o.data)), + nb_components(std::exchange(o.nb_components, 1)), + offset(std::exchange(o.offset, 0)) {} /// Destructor virtual ~GridBase() = default; -/* -------------------------------------------------------------------------- */ -/* Iterator class */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Iterator class */ + /* ------------------------------------------------------------------------ */ public: using iterator = iterator_::iterator; using const_iterator = iterator_::iterator; public: /// Compute size virtual UInt computeSize() const = 0; /// Get internal data pointer (const) - const T * getInternalData() const {return this->data.data();} + const T* getInternalData() const { return this->data.data(); } /// Get internal data pointer (non-const) - T * getInternalData() {return this->data.data();} + T* getInternalData() { return this->data.data(); } /// Get number of components - UInt getNbComponents() const {return nb_components;} + UInt getNbComponents() const { return nb_components; } /// Set number of components - void setNbComponents(UInt n) {nb_components = n;} + void setNbComponents(UInt n) { nb_components = n; } /// Get offset - UInt getOffset() const {return offset;} + UInt getOffset() const { return offset; } /// Get total size - virtual UInt dataSize() const {return this->data.size(); } + virtual UInt dataSize() const { return this->data.size(); } /// Get number of points - UInt getNbPoints() const {return this->computeSize() / this->getNbComponents(); } + UInt getNbPoints() const { + return this->computeSize() / this->getNbComponents(); + } /// Set components - void uniformSetComponents(const GridBase & vec); + void uniformSetComponents(const GridBase& vec); -/* -------------------------------------------------------------------------- */ -/* Iterator methods */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Iterator methods */ + /* ------------------------------------------------------------------------ */ virtual iterator begin(UInt n = 1) = 0; virtual iterator end(UInt n = 1) = 0; virtual const_iterator begin(UInt n = 1) const = 0; virtual const_iterator end(UInt n = 1) const = 0; -/* -------------------------------------------------------------------------- */ -/* Operators */ -/* -------------------------------------------------------------------------- */ -#define VEC_OPERATOR(op) \ - template \ - GridBase & operator op(const GridBase & other) \ + /* ------------------------------------------------------------------------ */ + /* Operators */ + /* ------------------------------------------------------------------------ */ + inline T& operator()(UInt i) { return this->data[i]; } + + inline const T& operator()(UInt i) const { return this->data[i]; } + +#define VEC_OPERATOR(op) \ + template \ + GridBase& operator op(const GridBase& other) VEC_OPERATOR(+=); VEC_OPERATOR(*=); VEC_OPERATOR(-=); VEC_OPERATOR(/=); #undef VEC_OPERATOR template - T dot(const GridBase & other); + T dot(const GridBase& other) const; -#define SCALAR_OPERATOR(op) \ - GridBase & operator op(const T & e) \ +#define SCALAR_OPERATOR(op) GridBase& operator op(const T& e) SCALAR_OPERATOR(+=); SCALAR_OPERATOR(*=); SCALAR_OPERATOR(-=); SCALAR_OPERATOR(/=); SCALAR_OPERATOR(=); #undef SCALAR_OPERATOR - virtual GridBase & operator=(const GridBase & o); + GridBase& operator=(const GridBase& o); -/* -------------------------------------------------------------------------- */ -/* Min/max */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Min/max */ + /* ------------------------------------------------------------------------ */ T min() const; T max() const; T sum() const; - T mean() const { return sum() / dataSize(); } + T mean() const { return sum() / static_cast(dataSize()); } T var() const; -/* -------------------------------------------------------------------------- */ -/* Move/Copy */ -/* -------------------------------------------------------------------------- */ + /* ------------------------------------------------------------------------ */ + /* Move/Copy */ + /* ------------------------------------------------------------------------ */ public: template - void copy(const GridBase & other) { + void copy(const GridBase& other) { data = other.data; nb_components = other.nb_components; offset = other.offset; } template - void move(GridBase && other) { + void move(GridBase&& other) { data = std::move(other.data); nb_components = std::exchange(other.nb_components, 1); offset = std::exchange(other.offset, 0); } protected: Array data; UInt nb_components = 1; UInt offset = 0; }; /* -------------------------------------------------------------------------- */ template -void GridBase::uniformSetComponents(const GridBase &vec) { +void GridBase::uniformSetComponents(const GridBase& vec) { if (!(vec.dataSize() == this->nb_components)) - TAMAAS_EXCEPTION("Cannot set grid field with values of vector"); + TAMAAS_EXCEPTION("Cannot set grid field with values of vector"); - auto begin_it = begin(), end_it = end(); + auto begin_it(begin()); + auto end_it(end()); // silencing nvcc warnings #pragma omp parallel for - for (auto it = begin() ; it < end_it ; ++it) { + for (auto it = begin(); it < end_it; ++it) { UInt i = it - begin_it; *it = vec.data[i % this->nb_components]; } } -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- + */ -#define SCALAR_OPERATOR_IMPL(op) \ - template \ - inline GridBase & GridBase::operator op(const T & e) { \ - _Pragma("omp parallel for") \ - for (auto it = this->begin() ; it < this->end() ; ++it) { \ - *it op e; \ - } \ - return *this; \ - } \ +#define SCALAR_OPERATOR_IMPL(op) \ + template \ + inline GridBase& GridBase::operator op(const T& e) { \ + Loop::loop([e] CUDA_LAMBDA(T& val) { val op e; }, *this); \ + return *this; \ + } SCALAR_OPERATOR_IMPL(+=); SCALAR_OPERATOR_IMPL(*=); SCALAR_OPERATOR_IMPL(-=); SCALAR_OPERATOR_IMPL(/=); SCALAR_OPERATOR_IMPL(=); #undef SCALAR_OPERATOR_IMPL /* -------------------------------------------------------------------------- */ -#define VEC_OPERATOR_IMPL(op) \ - template \ - template \ - inline GridBase & GridBase::operator op(const GridBase & other) { \ - TAMAAS_ASSERT(other.computeSize() == this->computeSize(), \ - "surface size does not match"); \ - auto begin_it = this->begin(), end_it = this->end(); \ - auto other_begin = other.begin(), other_it = other.begin(); \ - _Pragma("omp parallel for firstprivate(other_it)") \ - for (auto it = begin() ; it < end_it ; ++it) { \ - other_it = other_begin; \ - other_it += it - begin_it; \ - *it op *other_it; \ - } \ - return *this; \ - } \ +#define VEC_OPERATOR_IMPL(op) \ + template \ + template \ + inline GridBase& GridBase::operator op(const GridBase& other) { \ + TAMAAS_ASSERT(other.computeSize() == this->computeSize(), \ + "surface size does not match"); \ + Loop::loop([] CUDA_LAMBDA(T& x, const T1& y) { x op y; }, *this, other); \ + return *this; \ + } VEC_OPERATOR_IMPL(+=); VEC_OPERATOR_IMPL(-=); VEC_OPERATOR_IMPL(*=); VEC_OPERATOR_IMPL(/=); #undef VEC_OPERATOR /* -------------------------------------------------------------------------- */ template -GridBase & GridBase::operator=(const GridBase & o) { +GridBase& GridBase::operator=(const GridBase& o) { this->copy(o); return *this; } /* -------------------------------------------------------------------------- */ +using op = operation; + template inline T GridBase::min() const { - T val = std::numeric_limits::max(); - auto begin_it = begin(), end_it = end(); -#pragma omp parallel for reduction(min:val) - for (auto it = begin_it ; it < end_it ; ++it) { - val = std::min(*it, val); - } - return val; + // const auto id = [] CUDA_LAMBDA (const T&x){return x;}; + return Loop::reduce([] CUDA_LAMBDA(const T& x) { return x; }, *this); } /* -------------------------------------------------------------------------- */ template inline T GridBase::max() const { - T val = std::numeric_limits::lowest(); - auto begin_it = begin(), end_it = end(); -#pragma omp parallel for reduction(max:val) - for (auto it = begin_it ; it < end_it ; ++it) { - val = std::max(*it, val); - } - return val; + return Loop::reduce([] CUDA_LAMBDA(const T& x) { return x; }, *this); } /* -------------------------------------------------------------------------- */ template inline T GridBase::sum() const { - T val = 0; - auto begin_it = begin(), end_it = end(); -#pragma omp parallel for reduction(+:val) - for (auto it = begin_it ; it < end_it ; ++it) { - val += *it; - } - return val; + return Loop::reduce([] CUDA_LAMBDA(const T& x) { return x; }, + *this); } /* -------------------------------------------------------------------------- */ template inline T GridBase::var() const { - T var = 0; const T mu = mean(); - auto begin_it = begin(), end_it = end(); -#pragma omp parallel for reduction(+:var) - for (auto it = begin_it ; it < end_it ; ++it) { - var += (*it - mu) * (*it - mu); - } - + const T var = Loop::reduce( + [mu] CUDA_LAMBDA(const T& x) { return (x - mu) * (x - mu); }, *this); return var / (dataSize() - 1); } /* -------------------------------------------------------------------------- */ template template -T GridBase::dot(const GridBase & other) { - T res = 0; - auto begin_it = begin(), end_it = end(); - auto other_b = other.begin(), other_it = other.begin(); -#pragma omp parallel for firstprivate(other_it) reduction(+: res) - for (auto it = begin_it ; it < end_it ; ++it) { - other_it = other_b; - other_it += it - begin_it; - res += *it * *other_it; - } - - return res; +T GridBase::dot(const GridBase& other) const { + return Loop::reduce( + [] CUDA_LAMBDA(const T& x, const T1& y) { return x * y; }, *this, other); } - __END_TAMAAS__ - -#endif // __GRID_BASE_HH__ +#endif // __GRID_BASE_HH__ diff --git a/src/core/grid_hermitian.cpp b/src/core/grid_hermitian.cpp index bf4c5cd..4066c83 100644 --- a/src/core/grid_hermitian.cpp +++ b/src/core/grid_hermitian.cpp @@ -1,40 +1,42 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "grid_hermitian.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ -#define GRID_HERMITIAN_INSTANCIATE(type) template class GridHermitian; \ - template class GridHermitian; \ +#define GRID_HERMITIAN_INSTANCIATE(type) \ + template class GridHermitian; \ + template class GridHermitian; \ template class GridHermitian GRID_HERMITIAN_INSTANCIATE(Real); #undef GRID_HERMITIAN_INSTANCIATE __END_TAMAAS__ diff --git a/src/core/grid_hermitian.hh b/src/core/grid_hermitian.hh index e78d0c2..afef6a2 100644 --- a/src/core/grid_hermitian.hh +++ b/src/core/grid_hermitian.hh @@ -1,180 +1,159 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_HERMITIAN_HH__ #define __GRID_HERMITIAN_HH__ /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "grid.hh" -#include +#include "tamaas.hh" #include +#include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ -static std::complex dummy; +static complex dummy; /** * @brief Multi-dimensional, multi-component herimitian array * * This class represents an array of hermitian data, meaning it has dimensions * of: n1 * n2 * n3 * ... * (nx / 2 + 1) - * + * * However, it acts as a fully dimensioned array, returning a dummy reference * for data outside its real dimension, allowing one to write full (and * inefficient) loops without really worrying about the reduced dimension. * * It would however be better to just use the true dimensions of the surface * for all intents and purposes, as it saves computation time. */ template -class GridHermitian : public Grid, dim> { +class GridHermitian : public Grid, dim> { public: - typedef std::complex value_type; -/* -------------------------------------------------------------------------- */ -/* Constructors */ -/* -------------------------------------------------------------------------- */ + typedef complex value_type; + /* ------------------------------------------------------------------------ */ + /* Constructors */ + /* ------------------------------------------------------------------------ */ public: GridHermitian() = default; - GridHermitian(const GridHermitian & o) = default; - GridHermitian(GridHermitian && o) = default; + GridHermitian(const GridHermitian& o) = default; + GridHermitian(GridHermitian&& o) = default; using Grid::Grid; - using Grid, dim>::operator=; -/* -------------------------------------------------------------------------- */ -/* Access operators */ -/* -------------------------------------------------------------------------- */ + using Grid, dim>::operator=; + /* ------------------------------------------------------------------------ */ + /* Access operators */ + /* ------------------------------------------------------------------------ */ template - inline std::complex & operator()(T1... args); + inline complex& operator()(T1... args); template - inline const std::complex & operator()(T1... args) const; + inline const complex& operator()(T1... args) const; - - static std::array hermitianDimensions(const std::array & n) { + static std::array + hermitianDimensions(const std::array& n) { std::array hn(n); - hn[dim-1] /= 2; - hn[dim-1] += 1; + hn[dim - 1] /= 2; + hn[dim - 1] += 1; return hn; } private: template - inline void packTuple(UInt * t, UInt i, T1... args) const; + inline void packTuple(UInt* t, UInt i, T1... args) const; template - inline void packTuple(UInt * t, UInt i) const; - + inline void packTuple(UInt* t, UInt i) const; }; /* -------------------------------------------------------------------------- */ /* Inline function definitions */ /* -------------------------------------------------------------------------- */ template template -inline void GridHermitian::packTuple(UInt * t, UInt i, T1... args) const { +inline void GridHermitian::packTuple(UInt* t, UInt i, + T1... args) const { *t = i; - packTuple(t+1, args...); + packTuple(t + 1, args...); } template template -inline void GridHermitian::packTuple(UInt * t, UInt i) const { +inline void GridHermitian::packTuple(UInt* t, UInt i) const { *t = i; } template template -inline std::complex & GridHermitian::operator()(T1... args) { - TAMAAS_ASSERT(sizeof...(T1) == dim + 1 || sizeof...(T1) == 1, - "operator() does not match dimension"); - if (sizeof...(T1) == 1 && dim != 1) { - UInt tuple[1] = {0}; - packTuple(tuple, args...); - if (tuple[0] >= this->data.size()) { - TAMAAS_DEBUG_EXCEPTION("out of bonds access on hermitian surface"); - dummy = std::complex(0,0); - return dummy; +inline complex& GridHermitian::operator()(T1... args) { + constexpr UInt nargs = sizeof...(T1); + static_assert(nargs <= dim + 1, "Too many arguments"); + UInt last_index = std::get(std::forward_as_tuple(args...)); + if (nargs != 1 && last_index >= this->n[dim - 1]) { + std::array tuple = {{0}}; + packTuple(tuple.data(), args...); + + for (UInt i = 0; i < dim; i++) { + if (tuple[i] && i != dim - 1) + tuple[i] = this->n[i] - tuple[i]; + else if (tuple[i] && i == dim - 1) + tuple[i] = 2 * (this->n[i] - 1) - tuple[i]; } - else return this->Grid, dim>::operator()(args...); - } - std::array tuple = {{0}}; - packTuple(tuple.data(), args...); - - // reverse tuple if necessary - if (tuple[dim-1] >= this->n[dim-1]) { - for (UInt i = 0 ; i < dim ; i++) { - if (tuple[i] && i != dim-1) - tuple[i] = this->n[i]-tuple[i]; - else if (tuple[i] && i == dim-1) - tuple[i] = 2*(this->n[i]-1) - tuple[i]; - } - - dummy = std::conj(this->Grid, dim>::operator()(tuple)); + dummy = conj(this->Grid, dim>::operator()(tuple)); return dummy; - } else { - return this->Grid, dim>::operator()(tuple); } + + else + return Grid, dim>::operator()(args...); } template template -inline const std::complex & GridHermitian::operator()(T1... args) const { - TAMAAS_ASSERT(sizeof...(T1) == dim + 1 || sizeof...(T1) == 1, - "operator() does not match dimension"); - if (sizeof...(T1) == 1 && dim != 1) { - UInt tuple[1] = {0}; - packTuple(tuple, args...); - if (tuple[0] >= this->data.size()) { - TAMAAS_DEBUG_EXCEPTION("out of bonds access on hermitian surface"); - dummy = std::complex(0,0); - return dummy; +inline const complex& GridHermitian::operator()(T1... args) const { + constexpr UInt nargs = sizeof...(T1); + static_assert(nargs <= dim + 1, "Too many arguments"); + UInt last_index = std::get(std::forward_as_tuple(args...)); + if (nargs != 1 && last_index >= this->n[dim - 1]) { + std::array tuple = {{0}}; + packTuple(tuple.data(), args...); + + for (UInt i = 0; i < dim; i++) { + if (tuple[i] && i != dim - 1) + tuple[i] = this->n[i] - tuple[i]; + else if (tuple[i] && i == dim - 1) + tuple[i] = 2 * (this->n[i] - 1) - tuple[i]; } - else return this->Grid, dim>::operator()(args...); - } - - std::array tuple = {0}; - packTuple(tuple.data(), args...); - // reverse tuple if necessary - if (tuple[dim-1] >= this->n[dim-1]) { - for (UInt i = 0 ; i < dim ; i++) { - if (tuple[i] && i != dim-1) - tuple[i] = this->n[i]-tuple[i]; - else if (tuple[i] && i == dim-1) - tuple[i] = 2*(this->n[i]-1) - tuple[i]; - } - - dummy = std::conj(this->Grid, dim>::operator()(tuple)); + dummy = conj(this->Grid, dim>::operator()(tuple)); return dummy; - } else { - return this->Grid, dim>::operator()(tuple); } + + else + return Grid, dim>::operator()(args...); } __END_TAMAAS__ - - -#endif // __GRID_HERMITIAN_HH__ +#endif // __GRID_HERMITIAN_HH__ diff --git a/src/core/grid_tmpl.hh b/src/core/grid_tmpl.hh index ad13a87..abaf75e 100644 --- a/src/core/grid_tmpl.hh +++ b/src/core/grid_tmpl.hh @@ -1,175 +1,173 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_TMPL_HH__ #define __GRID_TMPL_HH__ /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "grid.hh" +#include "tamaas.hh" __BEGIN_TAMAAS__ template template -void Grid::init(const T1 & n, UInt nb_components) { +void Grid::init(const T1& n, UInt nb_components) { std::copy(n.begin(), n.end(), this->n.begin()); this->nb_components = nb_components; this->resize(this->n); } /* -------------------------------------------------------------------------- */ template inline UInt Grid::computeSize() const { UInt size = 1; - for (UInt i = 0 ; i < dim ; i++) size *= n[i]; + for (UInt i = 0; i < dim; i++) + size *= n[i]; size *= this->nb_components; return size; } /* -------------------------------------------------------------------------- */ template template -inline UInt Grid::unpackOffset(UInt offset, UInt index_pos, - UInt index, T1... rest) const { +inline UInt Grid::unpackOffset(UInt offset, UInt index_pos, UInt index, + T1... rest) const { offset += index * strides[index_pos]; - return unpackOffset(offset, index_pos+1, rest...); // tail-rec bb + return unpackOffset(offset, index_pos + 1, rest...); // tail-rec bb } template template inline UInt Grid::unpackOffset(UInt offset, UInt index_pos, - UInt index) const { + UInt index) const { return offset + index * strides[index_pos]; } template template -inline T & Grid::operator()(T1... args) { +inline T& Grid::operator()(T1... args) { /// Checking access integrity constexpr UInt nargs = sizeof...(T1); - static_assert(nargs == dim + 1 || - nargs == 1 || - nargs == dim, - "number of arguments in operator() does not match dimension"); + static_assert(nargs == dim + 1 || nargs == 1 || nargs == dim, + "number of arguments in operator() does not match dimension"); constexpr UInt start = (nargs == 1) ? dim : 0; UInt offset = unpackOffset(this->offset, start, args...); return this->data[offset]; } template template -inline const T & Grid::operator()(T1... args) const { +inline const T& Grid::operator()(T1... args) const { /// Checking access integrity constexpr UInt nargs = sizeof...(T1); - static_assert(nargs == dim + 1 || - nargs == 1 || - nargs == dim, - "number of arguments in operator() does not match dimension"); + static_assert(nargs == dim + 1 || nargs == 1 || nargs == dim, + "number of arguments in operator() does not match dimension"); constexpr UInt start = (nargs == 1) ? dim : 0; UInt offset = unpackOffset(this->offset, start, args...); return this->data[offset]; } /* -------------------------------------------------------------------------- */ template -inline UInt Grid::computeOffset(std::array tuple) const { +inline UInt Grid::computeOffset(std::array tuple) const { UInt offset = this->offset; - for (UInt i = 0 ; i < dim+1 ; i++) { + for (UInt i = 0; i < dim + 1; i++) { offset += tuple[i] * strides[i]; } return offset; } template -inline T & Grid::operator()(std::array tuple) { +inline T& Grid::operator()(std::array tuple) { UInt offset = computeOffset(tuple); return this->data[offset]; } template -inline const T & Grid::operator()(std::array tuple) const { +inline const T& Grid:: +operator()(std::array tuple) const { UInt offset = computeOffset(tuple); return this->data[offset]; } /* -------------------------------------------------------------------------- */ template -Grid & Grid::operator=(const Grid & other) { +Grid& Grid::operator=(const Grid& other) { this->copy(other); return *this; } template -Grid & Grid::operator=(Grid & other) { +Grid& Grid::operator=(Grid& other) { this->copy(other); return *this; } template -Grid & Grid::operator=(Grid && other) { +Grid& Grid::operator=(Grid&& other) { this->move(std::forward>(other)); return *this; } /* -------------------------------------------------------------------------- */ template template -void Grid::copy(const Grid & other) { +void Grid::copy(const Grid& other) { GridBase::copy(other); this->n = other.n; this->strides = other.strides; } template template -void Grid::move(Grid && other) { +void Grid::move(Grid&& other) { GridBase::move(std::forward>(other)); this->n = std::move(other.n); this->strides = std::move(other.strides); } /* -------------------------------------------------------------------------- */ /* Stream operator */ /* -------------------------------------------------------------------------- */ template -inline std::ostream & operator<<(std::ostream & stream, - const Grid & _this) { +inline std::ostream& operator<<(std::ostream& stream, + const Grid& _this) { _this.printself(stream); return stream; } - __END_TAMAAS__ /* -------------------------------------------------------------------------- */ -#endif // __GRID_TMPL_HH__ +#endif // __GRID_TMPL_HH__ diff --git a/src/core/grid_view.hh b/src/core/grid_view.hh index 7d80aaa..9bbe3d7 100644 --- a/src/core/grid_view.hh +++ b/src/core/grid_view.hh @@ -1,265 +1,244 @@ /** + * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_VIEW_HH__ #define __GRID_VIEW_HH__ /* -------------------------------------------------------------------------- */ -#include "tamaas.hh" #include "grid.hh" +#include "tamaas.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ /** * @brief View type on grid * /!\ iterators do not work on this type of grid * */ -template