merge LBPM with spock

This commit is contained in:
James McClure 2021-12-12 11:36:47 -05:00
commit aa0b3a1cb0
158 changed files with 55630 additions and 46278 deletions

View File

@ -1,108 +1,13 @@
# To run clang tools:
# cd to root directory
# To update format only:
# find . -name "*.cpp" -or -name "*.cc" -or -name "*.h" -or -name "*.hpp" -or -name "*.I" | xargs -I{} clang-format -i {}
# git status -s . | sed s/^...// | grep -E "(\.cpp|\.h|\.cc|\.hpp|\.I)" | xargs -I{} clang-format -i {}
# To run modernize
# export CLANG_PATH=/packages/llvm/build/llvm-60
# export PATH=${CLANG_PATH}/bin:${CLANG_PATH}/share/clang:$PATH
# find src -name "*.cpp" -or -name "*.cc" | xargs -I{} clang-tidy -checks=modernize* -p=/projects/AtomicModel/build/debug -fix {}
# find src -name "*.cpp" -or -name "*.cc" -or -name "*.h" -or -name "*.hpp" -or -name "*.I" | xargs -I{} clang-format -i {}
# clang-format
---
Language: Cpp
# BasedOnStyle: LLVM
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: true
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
#BreakBeforeBraces: Stroustrup
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: true
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
...
# Our includes are not order-agnostic
SortIncludes: false
# Some of our comments include insightful insight
ReflowComments: false
...

13
.clang-format-2 Normal file
View File

@ -0,0 +1,13 @@
# clang-format
---
Language: Cpp
BasedOnStyle: LLVM
AccessModifierOffset: -4
IndentWidth: 4
# Our includes are not order-agnostic
SortIncludes: false
# Some of our comments include insightful insight
ReflowComments: false
...

124
.github/workflows/c-cpp.yml vendored Normal file
View File

@ -0,0 +1,124 @@
name: LBPM CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build-and-test:
runs-on: ubuntu-latest
env:
LBPM_ZLIB_DIR: /home/runner/extlib/zlib
LBPM_HDF5_DIR: /home/runner/extlib/hdf5
LBPM_SILO_DIR: /home/runner/extlib/silo
MPI_DIR: /home/runner/.openmpi
steps:
- name: download dependencies
run: |
echo $LBPM_ZLIB_DIR
echo $LBPM_HDF5_DIR
echo $LBPM_SILO_DIR
echo $GITHUB_PATH
echo $GITHUB_WORKSPACE
sudo apt-get update -y
wget https://bitbucket.org/AdvancedMultiPhysics/tpl-builder/downloads/silo-4.10.2.tar.gz
wget https://www.zlib.net/zlib-1.2.11.tar.gz
wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.8/hdf5-1.8.12/src/hdf5-1.8.12.tar.gz
#wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.8/hdf5-1.8.10/src/hdf5-1.8.10.tar.gz
tar -xzvf zlib-1.2.11.tar.gz
tar -xzvf hdf5-1.8.12.tar.gz
tar -xzvf silo-4.10.2.tar.gz
- name: check out commit
uses: actions/checkout@v2
with:
path: LBPM
- name: install-openmpi
run: |
wget https://download.open-mpi.org/release/open-mpi/v3.1/openmpi-3.1.2.tar.gz
tar -xvf ./openmpi-3.1.2.tar.gz
./openmpi-3.1.2/configure --prefix="$HOME/.openmpi"
make -j
sudo make install
echo "$HOME/.openmpi/bin" >> $GITHUB_PATH
- name: install zlib dependencies
run: |
cd zlib-1.2.11
./configure --prefix=$LBPM_ZLIB_DIR
make
sudo make install
cd ..
- name: install hdf5 dependencies
run: |
cd hdf5-1.8.12
CC=/home/runner/.openmpi/bin/mpicc CXX=/home/runner/.openmpi/bin/mpicxx CXXFLAGS="-fPIC -O3 -std=c++14" \
./configure --prefix=$LBPM_HDF5_DIR --enable-parallel --enable-shared --with-zlib=$LBPM_ZLIB_DIR
make
sudo make install
cd ..
- name: install silo dependencies
run: |
cd silo-4.10.2
CC=$MPI_DIR/bin/mpicc CXX=$MPI_DIR/bin/mpicxx CXXFLAGS="-fPIC -O3 -std=c++14" \
./configure --prefix=$LBPM_SILO_DIR -with-hdf5="$LBPM_HDF5_DIR/include,$LBPM_HDF5_DIR/lib" --enable-static
make
sudo make install
cd ..
- name: configure cmake
run: |
mkdir build
cd build
rm -rf CMake*
cmake \
-D CMAKE_BUILD_TYPE:STRING=Release \
-D CMAKE_C_COMPILER:PATH=$MPI_DIR/bin/mpicc \
-D CMAKE_CXX_COMPILER:PATH=$MPI_DIR/bin/mpicxx \
-D MPI_CXX_COMPILER=$MPI_DIR/bin/mpicxx \
-D CMAKE_C_FLAGS="-fPIC" \
-D CMAKE_CXX_FLAGS="-fPIC" \
-D CMAKE_CXX_STD=14 \
-D TEST_MAX_PROCS=1 \
-D USE_TIMER=0 \
-D TIMER_DIRECTORY=$LBPM_TIMER_DIR \
-D USE_NETCDF=0 \
-D NETCDF_DIRECTORY=$LBPM_NETCDF_DIR \
-D USE_SILO=1 \
-D HDF5_DIRECTORY=$LBPM_HDF5_DIR \
-D SILO_DIRECTORY=$LBPM_SILO_DIR \
-D USE_CUDA=0 \
$GITHUB_WORKSPACE/LBPM
- name: build and make
run: |
cd build
make
sudo make install
cd ..
- name: tests
run: |
cd build
ctest

View File

@ -0,0 +1,41 @@
name: Install OpenMPI test
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
install-openmpi:
runs-on: ubuntu-latest
steps:
- name: check path
run: |
echo $PATH
echo $GITHUB_PATH
cmake --version
- name: download-openmpi
run: wget https://download.open-mpi.org/release/open-mpi/v4.0/openmpi-4.0.2.tar.gz
- name: extract-openmpi
run: tar -xvf ./openmpi-4.0.2.tar.gz
- name: configure-openmpi
run: ./openmpi-4.0.2/configure --prefix="/home/${USER}/.openmpi"
- name: install-openmpi
run: |
make -j
sudo make install
- name: setting path
run: |
echo "/home/${USER}/.openmpi/bin" >> $GITHUB_PATH
#echo "/home/${USER}/.openmpi/bin" >> $PATH
- name: checking version
run: mpirun --version

View File

@ -14,7 +14,6 @@ MESSAGE("====================")
SET( PROJ LBPM ) # Set the project name for CMake
SET( LBPM_LIB lbpm-wia ) # Set the final library name
SET( LBPM_INC ) # Set an optional subfolder for includes (e.g. include/name/...)
SET( TEST_MAX_PROCS 16 )
# Initialize the project

View File

@ -274,7 +274,7 @@ std::vector<IO::MeshDatabase> writeMeshesHDF5( const std::vector<IO::MeshDataStr
std::vector<IO::MeshDatabase> writeMeshesHDF5(
const std::vector<IO::MeshDataStruct> &, const std::string &, IO::FileFormat, int )
const std::vector<IO::MeshDataStruct> &, const std::string &, IO::FileFormat, int, Xdmf & )
{
return std::vector<IO::MeshDatabase>();
}

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IO_HELPERS_INC
#define IO_HELPERS_INC

View File

@ -1,3 +1,33 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Mesh.h"
#include "IO/IOHelpers.h"
#include "common/Utilities.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MESH_INC
#define MESH_INC

View File

@ -1,3 +1,33 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "IO/MeshDatabase.h"
#include "IO/IOHelpers.h"
#include "IO/Mesh.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MeshDatabase_INC
#define MeshDatabase_INC

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "IO/PIO.h"
#include "common/MPI.h"
#include "common/Utilities.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_PIO
#define included_PIO

View File

@ -1,3 +1,33 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_PIO_hpp
#define included_PIO_hpp

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "IO/Reader.h"
#include "IO/HDF5_IO.h"
#include "IO/IOHelpers.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef READER_INC
#define READER_INC

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "IO/Writer.h"
#include "IO/HDF5_IO.h"
#include "IO/IOHelpers.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WRITER_INC
#define WRITER_INC

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "IO/netcdf.h"
#include "common/MPI.h"
#include "common/Utilities.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETCDF_READER
#define NETCDF_READER

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "IO/silo.h"
#include "common/MPI.h"
#include "common/Utilities.h"

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SILO_INTERFACE
#define SILO_INTERFACE

View File

@ -1,3 +1,33 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SILO_INTERFACE_HPP
#define SILO_INTERFACE_HPP

675
LICENSE
View File

@ -1,3 +1,677 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Copyright (c) 2015, JamesEMcClure
All rights reserved.
@ -21,4 +695,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -23,7 +23,7 @@ Configure, build & install procedure
* edit configure script from sample_scripts directory and configure (e.g.)
`/path/to/LBPM-WIA/sample_scripts/configure_desktop`
`/path/to/LBPM/sample_scripts/configure_desktop`
* compile and install

View File

@ -1,3 +1,18 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_StackTrace
#define included_StackTrace

View File

@ -1,33 +1,54 @@
#include "analysis/ElectroChemistry.h"
ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr<Domain> dm)
: Dm(dm) {
ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr <Domain> dm):
Dm(dm)
{
Nx = dm->Nx;
Ny = dm->Ny;
Nz = dm->Nz;
Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
Dm->nprocz() * 1.0;
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0;
ChemicalPotential.resize(Nx,Ny,Nz); ChemicalPotential.fill(0);
ElectricalPotential.resize(Nx,Ny,Nz); ElectricalPotential.fill(0);
ElectricalField_x.resize(Nx,Ny,Nz); ElectricalField_x.fill(0);
ElectricalField_y.resize(Nx,Ny,Nz); ElectricalField_y.fill(0);
ElectricalField_z.resize(Nx,Ny,Nz); ElectricalField_z.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
Rho.resize(Nx,Ny,Nz); Rho.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
IonFluxDiffusive_x.resize(Nx,Ny,Nz); IonFluxDiffusive_x.fill(0);
IonFluxDiffusive_y.resize(Nx,Ny,Nz); IonFluxDiffusive_y.fill(0);
IonFluxDiffusive_z.resize(Nx,Ny,Nz); IonFluxDiffusive_z.fill(0);
IonFluxAdvective_x.resize(Nx,Ny,Nz); IonFluxAdvective_x.fill(0);
IonFluxAdvective_y.resize(Nx,Ny,Nz); IonFluxAdvective_y.fill(0);
IonFluxAdvective_z.resize(Nx,Ny,Nz); IonFluxAdvective_z.fill(0);
IonFluxElectrical_x.resize(Nx,Ny,Nz); IonFluxElectrical_x.fill(0);
IonFluxElectrical_y.resize(Nx,Ny,Nz); IonFluxElectrical_y.fill(0);
IonFluxElectrical_z.resize(Nx,Ny,Nz); IonFluxElectrical_z.fill(0);
ChemicalPotential.resize(Nx, Ny, Nz);
ChemicalPotential.fill(0);
ElectricalPotential.resize(Nx, Ny, Nz);
ElectricalPotential.fill(0);
ElectricalField_x.resize(Nx, Ny, Nz);
ElectricalField_x.fill(0);
ElectricalField_y.resize(Nx, Ny, Nz);
ElectricalField_y.fill(0);
ElectricalField_z.resize(Nx, Ny, Nz);
ElectricalField_z.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
Rho.resize(Nx, Ny, Nz);
Rho.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
SDs.resize(Nx, Ny, Nz);
SDs.fill(0);
IonFluxDiffusive_x.resize(Nx, Ny, Nz);
IonFluxDiffusive_x.fill(0);
IonFluxDiffusive_y.resize(Nx, Ny, Nz);
IonFluxDiffusive_y.fill(0);
IonFluxDiffusive_z.resize(Nx, Ny, Nz);
IonFluxDiffusive_z.fill(0);
IonFluxAdvective_x.resize(Nx, Ny, Nz);
IonFluxAdvective_x.fill(0);
IonFluxAdvective_y.resize(Nx, Ny, Nz);
IonFluxAdvective_y.fill(0);
IonFluxAdvective_z.resize(Nx, Ny, Nz);
IonFluxAdvective_z.fill(0);
IonFluxElectrical_x.resize(Nx, Ny, Nz);
IonFluxElectrical_x.fill(0);
IonFluxElectrical_y.resize(Nx, Ny, Nz);
IonFluxElectrical_y.fill(0);
IonFluxElectrical_z.resize(Nx, Ny, Nz);
IonFluxElectrical_z.fill(0);
if (Dm->rank() == 0) {
bool WriteHeader = false;
@ -38,14 +59,12 @@ ElectroChemistryAnalyzer::ElectroChemistryAnalyzer(std::shared_ptr <Domain> dm):
WriteHeader = true;
TIMELOG = fopen("electrokinetic.csv", "a+");
if (WriteHeader)
{
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG, "TBD TBD\n");
}
}
}
ElectroChemistryAnalyzer::~ElectroChemistryAnalyzer() {
@ -54,11 +73,11 @@ ElectroChemistryAnalyzer::~ElectroChemistryAnalyzer(){
}
}
void ElectroChemistryAnalyzer::SetParams(){
void ElectroChemistryAnalyzer::SetParams() {}
}
void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, int timestep){
void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion,
ScaLBL_Poisson &Poisson,
ScaLBL_StokesModel &Stokes, int timestep) {
int i, j, k;
double Vin = 0.0;
@ -102,13 +121,16 @@ void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poiss
for (i = 1; i < Nx; i++) {
rho_avg_local[ion] += Rho(i, j, k);
rho_mu_avg_local[ion] += Rho(i, j, k) * Rho(i, j, k);
rho_psi_avg_local[ion] += Rho(i,j,k)*ElectricalPotential(i,j,k);
rho_psi_avg_local[ion] +=
Rho(i, j, k) * ElectricalPotential(i, j, k);
}
}
}
rho_avg_global[ion] = Dm->Comm.sumReduce(rho_avg_local[ion]) / Volume;
rho_mu_avg_global[ion]=Dm->Comm.sumReduce( rho_mu_avg_local[ion]) / Volume;
rho_psi_avg_global[ion]=Dm->Comm.sumReduce( rho_psi_avg_local[ion]) / Volume;
rho_mu_avg_global[ion] =
Dm->Comm.sumReduce(rho_mu_avg_local[ion]) / Volume;
rho_psi_avg_global[ion] =
Dm->Comm.sumReduce(rho_psi_avg_local[ion]) / Volume;
if (rho_avg_global[ion] > 0.0) {
rho_mu_avg_global[ion] /= rho_avg_global[ion];
@ -123,13 +145,18 @@ void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poiss
for (k = 1; k < Nz; k++) {
for (j = 1; j < Ny; j++) {
for (i = 1; i < Nx; i++) {
rho_mu_fluctuation_local[ion] += (Rho(i,j,k)*Rho(i,j,k) - rho_mu_avg_global[ion]);
rho_psi_fluctuation_local[ion] += (Rho(i,j,k)*ElectricalPotential(i,j,k) - rho_psi_avg_global[ion]);
rho_mu_fluctuation_local[ion] +=
(Rho(i, j, k) * Rho(i, j, k) - rho_mu_avg_global[ion]);
rho_psi_fluctuation_local[ion] +=
(Rho(i, j, k) * ElectricalPotential(i, j, k) -
rho_psi_avg_global[ion]);
}
}
}
rho_mu_fluctuation_global[ion]=Dm->Comm.sumReduce( rho_mu_fluctuation_local[ion]);
rho_psi_fluctuation_global[ion]=Dm->Comm.sumReduce( rho_psi_fluctuation_local[ion]);
rho_mu_fluctuation_global[ion] =
Dm->Comm.sumReduce(rho_mu_fluctuation_local[ion]);
rho_psi_fluctuation_global[ion] =
Dm->Comm.sumReduce(rho_psi_fluctuation_local[ion]);
}
if (Dm->rank() == 0) {
@ -157,20 +184,29 @@ void ElectroChemistryAnalyzer::Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poiss
} */
}
void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, std::shared_ptr<Database> input_db, int timestep){
void ElectroChemistryAnalyzer::WriteVis(ScaLBL_IonModel &Ion,
ScaLBL_Poisson &Poisson,
ScaLBL_StokesModel &Stokes,
std::shared_ptr<Database> input_db,
int timestep) {
auto vis_db = input_db->getDatabase("Visualization");
char VisName[40];
auto format = vis_db->getWithDefault<string>( "format", "hdf5" );
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1);
fillHalo<double> fillData(Dm->Comm, Dm->rank_info,
{Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2}, {1, 1, 1},
0, 1);
IO::initialize("","silo","false");
IO::initialize("",format,"false");
// Create the MeshDataStruct
visData.resize(1);
visData[0].meshName = "domain";
visData[0].mesh = std::make_shared<IO::DomainMesh>( Dm->rank_info,Dm->Nx-2,Dm->Ny-2,Dm->Nz-2,Dm->Lx,Dm->Ly,Dm->Lz );
visData[0].mesh =
std::make_shared<IO::DomainMesh>(Dm->rank_info, Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2, Dm->Lx, Dm->Ly, Dm->Lz);
//electric potential
auto ElectricPotentialVar = std::make_shared<IO::Variable>();
//electric field
@ -228,7 +264,8 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
IonConcentration[ion]->name = VisName;
IonConcentration[ion]->type = IO::VariableType::VolumeVariable;
IonConcentration[ion]->dim = 1;
IonConcentration[ion]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonConcentration[ion]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonConcentration[ion]);
}
}
@ -256,23 +293,29 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
// x-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxDiffusive_x", ion + 1);
IonFluxDiffusive[3 * ion + 0]->name = VisName;
IonFluxDiffusive[3*ion+0]->type = IO::VariableType::VolumeVariable;
IonFluxDiffusive[3 * ion + 0]->type =
IO::VariableType::VolumeVariable;
IonFluxDiffusive[3 * ion + 0]->dim = 1;
IonFluxDiffusive[3*ion+0]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxDiffusive[3 * ion + 0]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxDiffusive[3 * ion + 0]);
// y-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxDiffusive_y", ion + 1);
IonFluxDiffusive[3 * ion + 1]->name = VisName;
IonFluxDiffusive[3*ion+1]->type = IO::VariableType::VolumeVariable;
IonFluxDiffusive[3 * ion + 1]->type =
IO::VariableType::VolumeVariable;
IonFluxDiffusive[3 * ion + 1]->dim = 1;
IonFluxDiffusive[3*ion+1]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxDiffusive[3 * ion + 1]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxDiffusive[3 * ion + 1]);
// z-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxDiffusive_z", ion + 1);
IonFluxDiffusive[3 * ion + 2]->name = VisName;
IonFluxDiffusive[3*ion+2]->type = IO::VariableType::VolumeVariable;
IonFluxDiffusive[3 * ion + 2]->type =
IO::VariableType::VolumeVariable;
IonFluxDiffusive[3 * ion + 2]->dim = 1;
IonFluxDiffusive[3*ion+2]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxDiffusive[3 * ion + 2]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxDiffusive[3 * ion + 2]);
}
}
@ -282,23 +325,29 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
// x-component of advective flux
sprintf(VisName, "Ion%zu_FluxAdvective_x", ion + 1);
IonFluxAdvective[3 * ion + 0]->name = VisName;
IonFluxAdvective[3*ion+0]->type = IO::VariableType::VolumeVariable;
IonFluxAdvective[3 * ion + 0]->type =
IO::VariableType::VolumeVariable;
IonFluxAdvective[3 * ion + 0]->dim = 1;
IonFluxAdvective[3*ion+0]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxAdvective[3 * ion + 0]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxAdvective[3 * ion + 0]);
// y-component of advective flux
sprintf(VisName, "Ion%zu_FluxAdvective_y", ion + 1);
IonFluxAdvective[3 * ion + 1]->name = VisName;
IonFluxAdvective[3*ion+1]->type = IO::VariableType::VolumeVariable;
IonFluxAdvective[3 * ion + 1]->type =
IO::VariableType::VolumeVariable;
IonFluxAdvective[3 * ion + 1]->dim = 1;
IonFluxAdvective[3*ion+1]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxAdvective[3 * ion + 1]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxAdvective[3 * ion + 1]);
// z-component of advective flux
sprintf(VisName, "Ion%zu_FluxAdvective_z", ion + 1);
IonFluxAdvective[3 * ion + 2]->name = VisName;
IonFluxAdvective[3*ion+2]->type = IO::VariableType::VolumeVariable;
IonFluxAdvective[3 * ion + 2]->type =
IO::VariableType::VolumeVariable;
IonFluxAdvective[3 * ion + 2]->dim = 1;
IonFluxAdvective[3*ion+2]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxAdvective[3 * ion + 2]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxAdvective[3 * ion + 2]);
}
}
@ -308,23 +357,29 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
// x-component of electro-migrational flux
sprintf(VisName, "Ion%zu_FluxElectrical_x", ion + 1);
IonFluxElectrical[3 * ion + 0]->name = VisName;
IonFluxElectrical[3*ion+0]->type = IO::VariableType::VolumeVariable;
IonFluxElectrical[3 * ion + 0]->type =
IO::VariableType::VolumeVariable;
IonFluxElectrical[3 * ion + 0]->dim = 1;
IonFluxElectrical[3*ion+0]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxElectrical[3 * ion + 0]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxElectrical[3 * ion + 0]);
// y-component of electro-migrational flux
sprintf(VisName, "Ion%zu_FluxElectrical_y", ion + 1);
IonFluxElectrical[3 * ion + 1]->name = VisName;
IonFluxElectrical[3*ion+1]->type = IO::VariableType::VolumeVariable;
IonFluxElectrical[3 * ion + 1]->type =
IO::VariableType::VolumeVariable;
IonFluxElectrical[3 * ion + 1]->dim = 1;
IonFluxElectrical[3*ion+1]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxElectrical[3 * ion + 1]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxElectrical[3 * ion + 1]);
// z-component of electro-migrational flux
sprintf(VisName, "Ion%zu_FluxElectrical_z", ion + 1);
IonFluxElectrical[3 * ion + 2]->name = VisName;
IonFluxElectrical[3*ion+2]->type = IO::VariableType::VolumeVariable;
IonFluxElectrical[3 * ion + 2]->type =
IO::VariableType::VolumeVariable;
IonFluxElectrical[3 * ion + 2]->dim = 1;
IonFluxElectrical[3*ion+2]->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
IonFluxElectrical[3 * ion + 2]->data.resize(Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2);
visData[0].vars.push_back(IonFluxElectrical[3 * ion + 2]);
}
}
@ -361,20 +416,27 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
sprintf(VisName, "IonConcentration_%zu", ion + 1);
//IonConcentration[ion]->name = VisName;
ASSERT(visData[0].vars[1 + ion]->name == VisName);
Array<double>& IonConcentrationData = visData[0].vars[1+ion]->data;
Array<double> &IonConcentrationData =
visData[0].vars[1 + ion]->data;
Ion.getIonConcentration(Rho, ion);
fillData.copy(Rho, IonConcentrationData);
}
}
if (vis_db->getWithDefault<bool>("save_velocity", false)) {
ASSERT(visData[0].vars[1+Ion.number_ion_species+0]->name=="Velocity_x");
ASSERT(visData[0].vars[1+Ion.number_ion_species+1]->name=="Velocity_y");
ASSERT(visData[0].vars[1+Ion.number_ion_species+2]->name=="Velocity_z");
ASSERT(visData[0].vars[1 + Ion.number_ion_species + 0]->name ==
"Velocity_x");
ASSERT(visData[0].vars[1 + Ion.number_ion_species + 1]->name ==
"Velocity_y");
ASSERT(visData[0].vars[1 + Ion.number_ion_species + 2]->name ==
"Velocity_z");
Stokes.getVelocity(Vel_x, Vel_y, Vel_z);
Array<double>& VelxData = visData[0].vars[1+Ion.number_ion_species+0]->data;
Array<double>& VelyData = visData[0].vars[1+Ion.number_ion_species+1]->data;
Array<double>& VelzData = visData[0].vars[1+Ion.number_ion_species+2]->data;
Array<double> &VelxData =
visData[0].vars[1 + Ion.number_ion_species + 0]->data;
Array<double> &VelyData =
visData[0].vars[1 + Ion.number_ion_species + 1]->data;
Array<double> &VelzData =
visData[0].vars[1 + Ion.number_ion_species + 2]->data;
fillData.copy(Vel_x, VelxData);
fillData.copy(Vel_y, VelyData);
fillData.copy(Vel_z, VelzData);
@ -386,20 +448,30 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
// x-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxDiffusive_x", ion + 1);
//IonFluxDiffusive[3*ion+0]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species+3*ion+0]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species + 3 * ion + 0]
->name == VisName);
// y-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxDiffusive_y", ion + 1);
//IonFluxDiffusive[3*ion+1]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species+3*ion+1]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species + 3 * ion + 1]
->name == VisName);
// z-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxDiffusive_z", ion + 1);
//IonFluxDiffusive[3*ion+2]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species+3*ion+2]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species + 3 * ion + 2]
->name == VisName);
Array<double>& IonFluxData_x = visData[0].vars[4+Ion.number_ion_species+3*ion+0]->data;
Array<double>& IonFluxData_y = visData[0].vars[4+Ion.number_ion_species+3*ion+1]->data;
Array<double>& IonFluxData_z = visData[0].vars[4+Ion.number_ion_species+3*ion+2]->data;
Ion.getIonFluxDiffusive(IonFluxDiffusive_x,IonFluxDiffusive_y,IonFluxDiffusive_z,ion);
Array<double> &IonFluxData_x =
visData[0].vars[4 + Ion.number_ion_species + 3 * ion + 0]->data;
Array<double> &IonFluxData_y =
visData[0].vars[4 + Ion.number_ion_species + 3 * ion + 1]->data;
Array<double> &IonFluxData_z =
visData[0].vars[4 + Ion.number_ion_species + 3 * ion + 2]->data;
Ion.getIonFluxDiffusive(IonFluxDiffusive_x, IonFluxDiffusive_y,
IonFluxDiffusive_z, ion);
fillData.copy(IonFluxDiffusive_x, IonFluxData_x);
fillData.copy(IonFluxDiffusive_y, IonFluxData_y);
fillData.copy(IonFluxDiffusive_z, IonFluxData_z);
@ -412,20 +484,36 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
// x-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxAdvective_x", ion + 1);
//IonFluxDiffusive[3*ion+0]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+0]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 0]
->name == VisName);
// y-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxAdvective_y", ion + 1);
//IonFluxDiffusive[3*ion+1]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+1]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 1]
->name == VisName);
// z-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxAdvective_z", ion + 1);
//IonFluxDiffusive[3*ion+2]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+2]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 2]
->name == VisName);
Array<double>& IonFluxData_x = visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+0]->data;
Array<double>& IonFluxData_y = visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+1]->data;
Array<double>& IonFluxData_z = visData[0].vars[4+Ion.number_ion_species*(1+3)+3*ion+2]->data;
Ion.getIonFluxAdvective(IonFluxAdvective_x,IonFluxAdvective_y,IonFluxAdvective_z,ion);
Array<double> &IonFluxData_x =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 0]
->data;
Array<double> &IonFluxData_y =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 1]
->data;
Array<double> &IonFluxData_z =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 3) + 3 * ion + 2]
->data;
Ion.getIonFluxAdvective(IonFluxAdvective_x, IonFluxAdvective_y,
IonFluxAdvective_z, ion);
fillData.copy(IonFluxAdvective_x, IonFluxData_x);
fillData.copy(IonFluxAdvective_y, IonFluxData_y);
fillData.copy(IonFluxAdvective_z, IonFluxData_z);
@ -438,20 +526,36 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
// x-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxElectrical_x", ion + 1);
//IonFluxDiffusive[3*ion+0]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+0]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 0]
->name == VisName);
// y-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxElectrical_y", ion + 1);
//IonFluxDiffusive[3*ion+1]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+1]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 1]
->name == VisName);
// z-component of diffusive flux
sprintf(VisName, "Ion%zu_FluxElectrical_z", ion + 1);
//IonFluxDiffusive[3*ion+2]->name = VisName;
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+2]->name==VisName);
ASSERT(visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 2]
->name == VisName);
Array<double>& IonFluxData_x = visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+0]->data;
Array<double>& IonFluxData_y = visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+1]->data;
Array<double>& IonFluxData_z = visData[0].vars[4+Ion.number_ion_species*(1+6)+3*ion+2]->data;
Ion.getIonFluxElectrical(IonFluxElectrical_x,IonFluxElectrical_y,IonFluxElectrical_z,ion);
Array<double> &IonFluxData_x =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 0]
->data;
Array<double> &IonFluxData_y =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 1]
->data;
Array<double> &IonFluxData_z =
visData[0]
.vars[4 + Ion.number_ion_species * (1 + 6) + 3 * ion + 2]
->data;
Ion.getIonFluxElectrical(IonFluxElectrical_x, IonFluxElectrical_y,
IonFluxElectrical_z, ion);
fillData.copy(IonFluxElectrical_x, IonFluxData_x);
fillData.copy(IonFluxElectrical_y, IonFluxData_y);
fillData.copy(IonFluxElectrical_z, IonFluxData_z);
@ -459,13 +563,23 @@ void ElectroChemistryAnalyzer::WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &P
}
if (vis_db->getWithDefault<bool>("save_electric_field", false)) {
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+9)+0]->name=="ElectricField_x");
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+9)+1]->name=="ElectricField_y");
ASSERT(visData[0].vars[4+Ion.number_ion_species*(1+9)+2]->name=="ElectricField_z");
Poisson.getElectricField(ElectricalField_x, ElectricalField_y, ElectricalField_z);
Array<double>& ElectricalFieldxData = visData[0].vars[4+Ion.number_ion_species*(1+9)+0]->data;
Array<double>& ElectricalFieldyData = visData[0].vars[4+Ion.number_ion_species*(1+9)+1]->data;
Array<double>& ElectricalFieldzData = visData[0].vars[4+Ion.number_ion_species*(1+9)+2]->data;
ASSERT(
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 0]->name ==
"ElectricField_x");
ASSERT(
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 1]->name ==
"ElectricField_y");
ASSERT(
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 2]->name ==
"ElectricField_z");
Poisson.getElectricField(ElectricalField_x, ElectricalField_y,
ElectricalField_z);
Array<double> &ElectricalFieldxData =
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 0]->data;
Array<double> &ElectricalFieldyData =
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 1]->data;
Array<double> &ElectricalFieldzData =
visData[0].vars[4 + Ion.number_ion_species * (1 + 9) + 2]->data;
fillData.copy(ElectricalField_x, ElectricalFieldxData);
fillData.copy(ElectricalField_y, ElectricalFieldyData);
fillData.copy(ElectricalField_z, ElectricalFieldzData);

View File

@ -57,11 +57,13 @@ public:
~ElectroChemistryAnalyzer();
void SetParams();
void Basic( ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, int timestep);
void WriteVis( ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson, ScaLBL_StokesModel &Stokes, std::shared_ptr<Database> input_db, int timestep);
void Basic(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson,
ScaLBL_StokesModel &Stokes, int timestep);
void WriteVis(ScaLBL_IonModel &Ion, ScaLBL_Poisson &Poisson,
ScaLBL_StokesModel &Stokes,
std::shared_ptr<Database> input_db, int timestep);
private:
FILE *TIMELOG;
};
#endif

View File

@ -11,8 +11,10 @@ FlowAdaptor::FlowAdaptor(ScaLBL_ColorModel &M){
timestep = -1;
timestep_previous = -1;
phi.resize(Nx,Ny,Nz); phi.fill(0); // phase indicator field
phi_t.resize(Nx,Ny,Nz); phi_t.fill(0); // time derivative for the phase indicator field
phi.resize(Nx, Ny, Nz);
phi.fill(0); // phase indicator field
phi_t.resize(Nx, Ny, Nz);
phi_t.fill(0); // time derivative for the phase indicator field
}
FlowAdaptor::~FlowAdaptor() {
@ -21,11 +23,16 @@ FlowAdaptor::~FlowAdaptor(){
double FlowAdaptor::ImageInit(ScaLBL_ColorModel &M, std::string Filename) {
int rank = M.rank;
int Nx = M.Nx; int Ny = M.Ny; int Nz = M.Nz;
if (rank==0) printf("Re-initializing fluids from file: %s \n", Filename.c_str());
int Nx = M.Nx;
int Ny = M.Ny;
int Nz = M.Nz;
if (rank == 0)
printf("Re-initializing fluids from file: %s \n", Filename.c_str());
M.Mask->Decomp(Filename);
for (int i=0; i<Nx*Ny*Nz; i++) M.id[i] = M.Mask->id[i]; // save what was read
for (int i=0; i<Nx*Ny*Nz; i++) M.Dm->id[i] = M.Mask->id[i]; // save what was read
for (int i = 0; i < Nx * Ny * Nz; i++)
M.id[i] = M.Mask->id[i]; // save what was read
for (int i = 0; i < Nx * Ny * Nz; i++)
M.Dm->id[i] = M.Mask->id[i]; // save what was read
double *PhaseLabel;
PhaseLabel = new double[Nx * Ny * Nz];
@ -39,8 +46,7 @@ double FlowAdaptor::ImageInit(ScaLBL_ColorModel &M, std::string Filename){
if (M.id[Nx * Ny * k + Nx * j + i] == 2) {
PoreCount++;
Count++;
}
else if (M.id[Nx*Ny*k+Nx*j+i] == 1){
} else if (M.id[Nx * Ny * k + Nx * j + i] == 1) {
PoreCount++;
}
}
@ -50,30 +56,38 @@ double FlowAdaptor::ImageInit(ScaLBL_ColorModel &M, std::string Filename){
Count = M.Dm->Comm.sumReduce(Count);
PoreCount = M.Dm->Comm.sumReduce(PoreCount);
if (rank==0) printf(" new saturation: %f (%f / %f) \n", Count / PoreCount, Count, PoreCount);
if (rank == 0)
printf(" new saturation: %f (%f / %f) \n", Count / PoreCount, Count,
PoreCount);
ScaLBL_CopyToDevice(M.Phi, PhaseLabel, Nx * Ny * Nz * sizeof(double));
M.Dm->Comm.barrier();
ScaLBL_D3Q19_Init(M.fq, M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0, M.ScaLBL_Comm->LastExterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, M.ScaLBL_Comm->FirstInterior(), M.ScaLBL_Comm->LastInterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0,
M.ScaLBL_Comm->LastExterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq,
M.ScaLBL_Comm->FirstInterior(),
M.ScaLBL_Comm->LastInterior(), M.Np);
M.Dm->Comm.barrier();
ScaLBL_CopyToHost(M.Averages->Phi.data(),M.Phi,Nx*Ny*Nz*sizeof(double));
ScaLBL_CopyToHost(M.Averages->Phi.data(), M.Phi,
Nx * Ny * Nz * sizeof(double));
delete PhaseLabel;
double saturation = Count / PoreCount;
return saturation;
}
double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M) {
double MASS_FRACTION_CHANGE = 0.006;
double FRACTIONAL_FLOW_EPSILON = 5e-6;
if (M.db->keyExists("FlowAdaptor")) {
auto flow_db = M.db->getDatabase("FlowAdaptor");
MASS_FRACTION_CHANGE = flow_db->getWithDefault<double>( "mass_fraction_factor", 0.006);
FRACTIONAL_FLOW_EPSILON = flow_db->getWithDefault<double>( "fractional_flow_epsilon", 5e-6);
MASS_FRACTION_CHANGE =
flow_db->getWithDefault<double>("mass_fraction_factor", 0.006);
FRACTIONAL_FLOW_EPSILON =
flow_db->getWithDefault<double>("fractional_flow_epsilon", 5e-6);
}
int Np = M.Np;
double dA, dB, phi;
@ -96,7 +110,9 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
ScaLBL_CopyToHost(Vel_y, &M.Velocity[Np], Np * sizeof(double));
ScaLBL_CopyToHost(Vel_z, &M.Velocity[2 * Np], Np * sizeof(double));
int Nx = M.Nx; int Ny = M.Ny; int Nz = M.Nz;
int Nx = M.Nx;
int Ny = M.Ny;
int Nz = M.Nz;
mass_a = mass_b = 0.0;
double maxSpeed = 0.0;
@ -110,8 +126,12 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
int n = M.Map(i, j, k);
//double distance = M.Averages->SDs(i,j,k);
if (!(n < 0)) {
dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
dA = Aq_tmp[n] + Aq_tmp[n + Np] + Aq_tmp[n + 2 * Np] +
Aq_tmp[n + 3 * Np] + Aq_tmp[n + 4 * Np] +
Aq_tmp[n + 5 * Np] + Aq_tmp[n + 6 * Np];
dB = Bq_tmp[n] + Bq_tmp[n + Np] + Bq_tmp[n + 2 * Np] +
Bq_tmp[n + 3 * Np] + Bq_tmp[n + 4 * Np] +
Bq_tmp[n + 5 * Np] + Bq_tmp[n + 6 * Np];
phi = (dA - dB) / (dA + dB);
Phase[n] = phi;
mass_a += dA;
@ -120,11 +140,11 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
vy = Vel_y[n];
vz = Vel_z[n];
double local_momentum = sqrt(vx * vx + vy * vy + vz * vz);
double local_weight = (FRACTIONAL_FLOW_EPSILON + local_momentum);
double local_weight =
(FRACTIONAL_FLOW_EPSILON + local_momentum);
if (phi > 0.0) {
sum_weights_A += local_weight * dA;
}
else {
} else {
sum_weights_B += local_weight * dB;
}
if (local_momentum > localMaxSpeed) {
@ -145,7 +165,8 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
//double total_momentum_A = sqrt(vax_global*vax_global+vay_global*vay_global+vaz_global*vaz_global);
//double total_momentum_B = sqrt(vbx_global*vbx_global+vby_global*vby_global+vbz_global*vbz_global);
/* compute the total mass change */
double TOTAL_MASS_CHANGE = MASS_FRACTION_CHANGE*(mass_a_global + mass_b_global);
double TOTAL_MASS_CHANGE =
MASS_FRACTION_CHANGE * (mass_a_global + mass_b_global);
if (fabs(TOTAL_MASS_CHANGE) > 0.1 * mass_a_global)
TOTAL_MASS_CHANGE = 0.1 * mass_a_global;
if (fabs(TOTAL_MASS_CHANGE) > 0.1 * mass_b_global)
@ -165,29 +186,42 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
vy = Vel_y[n];
vz = Vel_z[n];
double local_momentum = sqrt(vx * vx + vy * vy + vz * vz);
double local_weight = (FRACTIONAL_FLOW_EPSILON + local_momentum)/(FRACTIONAL_FLOW_EPSILON + maxSpeed);
double local_weight =
(FRACTIONAL_FLOW_EPSILON + local_momentum) /
(FRACTIONAL_FLOW_EPSILON + maxSpeed);
/* impose ceiling for spurious currents */
//if (local_momentum > maxSpeed) local_momentum = maxSpeed;
if (phi > 0.0) {
LOCAL_MASS_CHANGE = MASS_FACTOR_A * local_weight;
Aq_tmp[n] -= 0.3333333333333333 * LOCAL_MASS_CHANGE;
Aq_tmp[n+Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
Aq_tmp[n+2*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
Aq_tmp[n+3*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
Aq_tmp[n+4*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
Aq_tmp[n+5*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
Aq_tmp[n+6*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
Aq_tmp[n + Np] -=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Aq_tmp[n + 2 * Np] -=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Aq_tmp[n + 3 * Np] -=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Aq_tmp[n + 4 * Np] -=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Aq_tmp[n + 5 * Np] -=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Aq_tmp[n + 6 * Np] -=
0.1111111111111111 * LOCAL_MASS_CHANGE;
//DebugMassA[n] = (-1.0)*LOCAL_MASS_CHANGE;
}
else{
} else {
LOCAL_MASS_CHANGE = MASS_FACTOR_B * local_weight;
Bq_tmp[n] += 0.3333333333333333 * LOCAL_MASS_CHANGE;
Bq_tmp[n+Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
Bq_tmp[n+2*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
Bq_tmp[n+3*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
Bq_tmp[n+4*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
Bq_tmp[n+5*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
Bq_tmp[n+6*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
Bq_tmp[n + Np] +=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Bq_tmp[n + 2 * Np] +=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Bq_tmp[n + 3 * Np] +=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Bq_tmp[n + 4 * Np] +=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Bq_tmp[n + 5 * Np] +=
0.1111111111111111 * LOCAL_MASS_CHANGE;
Bq_tmp[n + 6 * Np] +=
0.1111111111111111 * LOCAL_MASS_CHANGE;
//DebugMassB[n] = LOCAL_MASS_CHANGE;
}
}
@ -195,27 +229,41 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
}
}
if (M.rank == 0) printf("Update Fractional Flow: change mass of fluid B by %f \n",TOTAL_MASS_CHANGE/mass_b_global);
if (M.rank == 0)
printf("Update Fractional Flow: change mass of fluid B by %f \n",
TOTAL_MASS_CHANGE / mass_b_global);
// Need to initialize Aq, Bq, Den, Phi directly
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
ScaLBL_CopyToDevice(M.Aq, Aq_tmp, 7 * Np * sizeof(double));
ScaLBL_CopyToDevice(M.Bq, Bq_tmp, 7 * Np * sizeof(double));
delete Aq_tmp;
delete Bq_tmp;
delete Vel_x;
delete Vel_y;
delete Vel_z;
delete Phase;
return (TOTAL_MASS_CHANGE);
}
void FlowAdaptor::Flatten(ScaLBL_ColorModel &M) {
ScaLBL_D3Q19_Init(M.fq, M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0, M.ScaLBL_Comm->LastExterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, M.ScaLBL_Comm->FirstInterior(), M.ScaLBL_Comm->LastInterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0,
M.ScaLBL_Comm->LastExterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq,
M.ScaLBL_Comm->FirstInterior(),
M.ScaLBL_Comm->LastInterior(), M.Np);
}
double FlowAdaptor::MoveInterface(ScaLBL_ColorModel &M) {
double INTERFACE_CUTOFF = M.color_db->getWithDefault<double>( "move_interface_cutoff", 0.1 );
double MOVE_INTERFACE_FACTOR = M.color_db->getWithDefault<double>( "move_interface_factor", 10.0 );
double INTERFACE_CUTOFF =
M.color_db->getWithDefault<double>("move_interface_cutoff", 0.1);
double MOVE_INTERFACE_FACTOR =
M.color_db->getWithDefault<double>("move_interface_factor", 10.0);
ScaLBL_CopyToHost(phi.data(), M.Phi, Nx * Ny * Nz * sizeof(double));
/* compute the local derivative of phase indicator field */
@ -230,13 +278,16 @@ double FlowAdaptor::MoveInterface(ScaLBL_ColorModel &M){
double value2 = phi(n);
double dist2 = factor * log((1.0 + value2) / (1.0 - value2));
phi_t(n) = value2;
if (value1 < INTERFACE_CUTOFF && value1 > -1*INTERFACE_CUTOFF && value2 < INTERFACE_CUTOFF && value2 > -1*INTERFACE_CUTOFF ){
if (value1 < INTERFACE_CUTOFF && value1 > -1 * INTERFACE_CUTOFF &&
value2 < INTERFACE_CUTOFF && value2 > -1 * INTERFACE_CUTOFF) {
/* time derivative of distance */
double dxdt = 0.125 * (dist2 - dist1);
/* extrapolate to move the distance further */
double dist3 = dist2 + MOVE_INTERFACE_FACTOR * dxdt;
/* compute the new phase interface */
phi_t(n) = (2.f*(exp(-2.f*beta*(dist3)))/(1.f+exp(-2.f*beta*(dist3))) - 1.f);
phi_t(n) = (2.f * (exp(-2.f * beta * (dist3))) /
(1.f + exp(-2.f * beta * (dist3))) -
1.f);
total_interface_displacement += fabs(MOVE_INTERFACE_FACTOR * dxdt);
total_interface_sites += 1.0;
}
@ -245,11 +296,14 @@ double FlowAdaptor::MoveInterface(ScaLBL_ColorModel &M){
return total_interface_sites;
}
double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_delta_volume){
double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M,
const double target_delta_volume) {
const RankInfoStruct rank_info(M.rank, M.nprocx, M.nprocy, M.nprocz);
auto rank = M.rank;
auto Nx = M.Nx; auto Ny = M.Ny; auto Nz = M.Nz;
auto Nx = M.Nx;
auto Ny = M.Ny;
auto Nz = M.Nz;
auto N = Nx * Ny * Nz;
double vF = 0.f;
double vS = 0.f;
@ -258,10 +312,12 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
bool USE_CONNECTED_NWP = false;
DoubleArray phase(Nx, Ny, Nz);
IntArray phase_label(Nx,Ny,Nz);;
IntArray phase_label(Nx, Ny, Nz);
;
DoubleArray phase_distance(Nx, Ny, Nz);
Array<char> phase_id(Nx, Ny, Nz);
fillHalo<double> fillDouble(M.Dm->Comm,M.Dm->rank_info,{Nx-2,Ny-2,Nz-2},{1,1,1},0,1);
fillHalo<double> fillDouble(M.Dm->Comm, M.Dm->rank_info,
{Nx - 2, Ny - 2, Nz - 2}, {1, 1, 1}, 0, 1);
// Basic algorithm to
// 1. Copy phase field to CPU
@ -271,7 +327,8 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
for (int k = 1; k < Nz - 1; k++) {
for (int j = 1; j < Ny - 1; j++) {
for (int i = 1; i < Nx - 1; i++) {
if (phase(i,j,k) > 0.f && M.Averages->SDs(i,j,k) > 0.f) count+=1.f;
if (phase(i, j, k) > 0.f && M.Averages->SDs(i, j, k) > 0.f)
count += 1.f;
}
}
}
@ -287,7 +344,8 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
double volume_connected = 0.0;
double second_biggest = 0.0;
if (USE_CONNECTED_NWP) {
ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,rank_info,phase,M.Averages->SDs,vF,vS,phase_label,M.Dm->Comm);
ComputeGlobalBlobIDs(Nx - 2, Ny - 2, Nz - 2, rank_info, phase,
M.Averages->SDs, vF, vS, phase_label, M.Dm->Comm);
M.Dm->Comm.barrier();
// only operate on component "0"ScaLBL_ColorModel &M,
@ -300,8 +358,7 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
if (label == 0) {
phase_id(i, j, k) = 0;
count += 1.0;
}
else
} else
phase_id(i, j, k) = 1;
if (label == 1) {
second_biggest += 1.0;
@ -311,8 +368,7 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
}
volume_connected = M.Dm->Comm.sumReduce(count);
second_biggest = M.Dm->Comm.sumReduce(second_biggest);
}
else {
} else {
// use the whole NWP
for (int k = 0; k < Nz; k++) {
for (int j = 0; j < Ny; j++) {
@ -320,12 +376,10 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
if (M.Averages->SDs(i, j, k) > 0.f) {
if (phase(i, j, k) > 0.f) {
phase_id(i, j, k) = 0;
}
else {
} else {
phase_id(i, j, k) = 1;
}
}
else {
} else {
phase_id(i, j, k) = 1;
}
}
@ -343,8 +397,10 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
for (int i = 0; i < Nx; i++) {
if (phase_distance(i, j, k) < 3.f) {
value = phase(i, j, k);
if (value > 1.f) value=1.f;
if (value < -1.f) value=-1.f;
if (value > 1.f)
value = 1.f;
if (value < -1.f)
value = -1.f;
// temp -- distance based on analytical form McClure, Prins et al, Comp. Phys. Comm.
temp = -factor * log((1.0 + value) / (1.0 - value));
/// use this approximation close to the object
@ -357,22 +413,30 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
}
}
}
if (rank == 0)
printf("Pathway volume / next largest ganglion %f \n",
volume_connected / second_biggest);
if (rank==0) printf("Pathway volume / next largest ganglion %f \n",volume_connected/second_biggest );
if (rank==0) printf("MorphGrow with target volume fraction change %f \n", target_delta_volume/volume_initial);
if (rank == 0)
printf("MorphGrow with target volume fraction change %f \n",
target_delta_volume / volume_initial);
double target_delta_volume_incremental = target_delta_volume;
if (fabs(target_delta_volume) > 0.01 * volume_initial)
target_delta_volume_incremental = 0.01*volume_initial*target_delta_volume/fabs(target_delta_volume);
target_delta_volume_incremental = 0.01 * volume_initial *
target_delta_volume /
fabs(target_delta_volume);
delta_volume = MorphGrow(M.Averages->SDs,phase_distance,phase_id,M.Averages->Dm, target_delta_volume_incremental, WallFactor);
delta_volume =
MorphGrow(M.Averages->SDs, phase_distance, phase_id, M.Averages->Dm,
target_delta_volume_incremental, WallFactor);
for (int k = 0; k < Nz; k++) {
for (int j = 0; j < Ny; j++) {
for (int i = 0; i < Nx; i++) {
if (phase_distance(i,j,k) < 0.0 ) phase_id(i,j,k) = 0;
else phase_id(i,j,k) = 1;
if (phase_distance(i, j, k) < 0.0)
phase_id(i, j, k) = 0;
else
phase_id(i, j, k) = 1;
//if (phase_distance(i,j,k) < 0.0 ) phase(i,j,k) = 1.0;
}
}
@ -388,7 +452,9 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
if (M.Averages->SDs(i, j, k) > 0.f) {
if (d < 3.f) {
//phase(i,j,k) = -1.0;
phase(i,j,k) = (2.f*(exp(-2.f*M.beta*d))/(1.f+exp(-2.f*M.beta*d))-1.f);
phase(i, j, k) = (2.f * (exp(-2.f * M.beta * d)) /
(1.f + exp(-2.f * M.beta * d)) -
1.f);
}
}
}
@ -409,18 +475,28 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
double volume_final = M.Dm->Comm.sumReduce(count);
delta_volume = (volume_final - volume_initial);
if (rank == 0) printf("Shell Aggregation: change fluid volume fraction by %f \n", delta_volume/volume_initial);
if (rank == 0) printf(" new saturation = %f \n", volume_final/(M.Mask->Porosity()*double((Nx-2)*(Ny-2)*(Nz-2)*M.nprocs)));
if (rank == 0)
printf("Shell Aggregation: change fluid volume fraction by %f \n",
delta_volume / volume_initial);
if (rank == 0)
printf(" new saturation = %f \n",
volume_final /
(M.Mask->Porosity() *
double((Nx - 2) * (Ny - 2) * (Nz - 2) * M.nprocs)));
// 6. copy back to the device
//if (rank==0) printf("MorphInit: copy data back to device\n");
ScaLBL_CopyToDevice(M.Phi, phase.data(), N * sizeof(double));
// 7. Re-initialize phase field and density
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0, M.ScaLBL_Comm->LastExterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, M.ScaLBL_Comm->FirstInterior(), M.ScaLBL_Comm->LastInterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0,
M.ScaLBL_Comm->LastExterior(), M.Np);
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq,
M.ScaLBL_Comm->FirstInterior(),
M.ScaLBL_Comm->LastInterior(), M.Np);
auto BoundaryCondition = M.BoundaryCondition;
if (BoundaryCondition == 1 || BoundaryCondition == 2 || BoundaryCondition == 3 || BoundaryCondition == 4){
if (BoundaryCondition == 1 || BoundaryCondition == 2 ||
BoundaryCondition == 3 || BoundaryCondition == 4) {
if (M.Dm->kproc() == 0) {
ScaLBL_SetSlice_z(M.Phi, 1.0, Nx, Ny, Nz, 0);
ScaLBL_SetSlice_z(M.Phi, 1.0, Nx, Ny, Nz, 1);
@ -435,8 +511,8 @@ double FlowAdaptor::ShellAggregation(ScaLBL_ColorModel &M, const double target_d
return delta_volume;
}
double FlowAdaptor::SeedPhaseField(ScaLBL_ColorModel &M, const double seed_water_in_oil){
double FlowAdaptor::SeedPhaseField(ScaLBL_ColorModel &M,
const double seed_water_in_oil) {
srand(time(NULL));
auto rank = M.rank;
auto Np = M.Np;
@ -450,11 +526,14 @@ double FlowAdaptor::SeedPhaseField(ScaLBL_ColorModel &M, const double seed_water
ScaLBL_CopyToHost(Aq_tmp, M.Aq, 7 * Np * sizeof(double));
ScaLBL_CopyToHost(Bq_tmp, M.Bq, 7 * Np * sizeof(double));
for (int n = 0; n < M.ScaLBL_Comm->LastExterior(); n++) {
double random_value = seed_water_in_oil * double(rand()) / RAND_MAX;
double dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
double dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
double dA = Aq_tmp[n] + Aq_tmp[n + Np] + Aq_tmp[n + 2 * Np] +
Aq_tmp[n + 3 * Np] + Aq_tmp[n + 4 * Np] +
Aq_tmp[n + 5 * Np] + Aq_tmp[n + 6 * Np];
double dB = Bq_tmp[n] + Bq_tmp[n + Np] + Bq_tmp[n + 2 * Np] +
Bq_tmp[n + 3 * Np] + Bq_tmp[n + 4 * Np] +
Bq_tmp[n + 5 * Np] + Bq_tmp[n + 6 * Np];
double phase_id = (dA - dB) / (dA + dB);
if (phase_id > 0.0) {
Aq_tmp[n] -= 0.3333333333333333 * random_value;
@ -476,10 +555,15 @@ double FlowAdaptor::SeedPhaseField(ScaLBL_ColorModel &M, const double seed_water
mass_loss += random_value * seed_water_in_oil;
}
for (int n=M.ScaLBL_Comm->FirstInterior(); n < M.ScaLBL_Comm->LastInterior(); n++){
for (int n = M.ScaLBL_Comm->FirstInterior();
n < M.ScaLBL_Comm->LastInterior(); n++) {
double random_value = seed_water_in_oil * double(rand()) / RAND_MAX;
double dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
double dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
double dA = Aq_tmp[n] + Aq_tmp[n + Np] + Aq_tmp[n + 2 * Np] +
Aq_tmp[n + 3 * Np] + Aq_tmp[n + 4 * Np] +
Aq_tmp[n + 5 * Np] + Aq_tmp[n + 6 * Np];
double dB = Bq_tmp[n] + Bq_tmp[n + Np] + Bq_tmp[n + 2 * Np] +
Bq_tmp[n + 3 * Np] + Bq_tmp[n + 4 * Np] +
Bq_tmp[n + 5 * Np] + Bq_tmp[n + 6 * Np];
double phase_id = (dA - dB) / (dA + dB);
if (phase_id > 0.0) {
Aq_tmp[n] -= 0.3333333333333333 * random_value;
@ -503,12 +587,15 @@ double FlowAdaptor::SeedPhaseField(ScaLBL_ColorModel &M, const double seed_water
count = M.Dm->Comm.sumReduce(count);
mass_loss = M.Dm->Comm.sumReduce(mass_loss);
if (rank == 0) printf("Remove mass %f from %f voxels \n",mass_loss,count);
if (rank == 0)
printf("Remove mass %f from %f voxels \n", mass_loss, count);
// Need to initialize Aq, Bq, Den, Phi directly
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
ScaLBL_CopyToDevice(M.Aq, Aq_tmp, 7 * Np * sizeof(double));
ScaLBL_CopyToDevice(M.Bq, Bq_tmp, 7 * Np * sizeof(double));
delete Aq_tmp;
delete Bq_tmp;
return (mass_loss);
}

View File

@ -12,7 +12,6 @@
#include "models/ColorModel.h"
/**
* \class FlowAdaptor
* @brief
@ -22,8 +21,6 @@
class FlowAdaptor {
public:
/**
* \brief Create a flow adaptor to operate on the LB model
* @param M ScaLBL_ColorModel
@ -65,7 +62,8 @@ public:
* \details Update fractional flow condition. Mass will be preferentially added or removed from
* phase regions based on where flow is occurring
* @param M ScaLBL_ColorModel
*/ double UpdateFractionalFlow(ScaLBL_ColorModel &M);
*/
double UpdateFractionalFlow(ScaLBL_ColorModel &M);
/**
* \brief image re-initialization
@ -82,6 +80,7 @@ public:
void Flatten(ScaLBL_ColorModel &M);
DoubleArray phi;
DoubleArray phi_t;
private:
int Nx, Ny, Nz;
int timestep;

View File

@ -1,20 +1,29 @@
#include "analysis/FreeEnergy.h"
FreeEnergyAnalyzer::FreeEnergyAnalyzer(std::shared_ptr <Domain> dm):
Dm(dm)
{
FreeEnergyAnalyzer::FreeEnergyAnalyzer(std::shared_ptr<Domain> dm) : Dm(dm) {
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0;
Nx = dm->Nx;
Ny = dm->Ny;
Nz = dm->Nz;
Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
Dm->nprocz() * 1.0;
ChemicalPotential.resize(Nx,Ny,Nz); ChemicalPotential.fill(0);
Phi.resize(Nx,Ny,Nz); Phi.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
Rho.resize(Nx,Ny,Nz); Rho.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
ChemicalPotential.resize(Nx, Ny, Nz);
ChemicalPotential.fill(0);
Phi.resize(Nx, Ny, Nz);
Phi.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
Rho.resize(Nx, Ny, Nz);
Rho.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
SDs.resize(Nx, Ny, Nz);
SDs.fill(0);
if (Dm->rank() == 0) {
bool WriteHeader = false;
@ -25,14 +34,12 @@ FreeEnergyAnalyzer::FreeEnergyAnalyzer(std::shared_ptr <Domain> dm):
WriteHeader = true;
TIMELOG = fopen("free.csv", "a+");
if (WriteHeader)
{
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG, "timestep\n");
}
}
}
FreeEnergyAnalyzer::~FreeEnergyAnalyzer() {
@ -41,9 +48,7 @@ FreeEnergyAnalyzer::~FreeEnergyAnalyzer(){
}
}
void FreeEnergyAnalyzer::SetParams(){
}
void FreeEnergyAnalyzer::SetParams() {}
void FreeEnergyAnalyzer::Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep) {
@ -73,19 +78,25 @@ void FreeEnergyAnalyzer::Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep){
} */
}
void FreeEnergyAnalyzer::WriteVis( ScaLBL_FreeLeeModel &LeeModel, std::shared_ptr<Database> input_db, int timestep){
void FreeEnergyAnalyzer::WriteVis(ScaLBL_FreeLeeModel &LeeModel,
std::shared_ptr<Database> input_db,
int timestep) {
auto vis_db = input_db->getDatabase("Visualization");
std::vector<IO::MeshDataStruct> visData;
fillHalo<double> fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1);
fillHalo<double> fillData(Dm->Comm, Dm->rank_info,
{Dm->Nx - 2, Dm->Ny - 2, Dm->Nz - 2}, {1, 1, 1},
0, 1);
IO::initialize("", "silo", "false");
// Create the MeshDataStruct
visData.resize(1);
visData[0].meshName = "domain";
visData[0].mesh = std::make_shared<IO::DomainMesh>( Dm->rank_info,Dm->Nx-2,Dm->Ny-2,Dm->Nz-2,Dm->Lx,Dm->Ly,Dm->Lz );
visData[0].mesh =
std::make_shared<IO::DomainMesh>(Dm->rank_info, Dm->Nx - 2, Dm->Ny - 2,
Dm->Nz - 2, Dm->Lx, Dm->Ly, Dm->Lz);
auto VisPhase = std::make_shared<IO::Variable>();
auto VisPressure = std::make_shared<IO::Variable>();
auto VisChemicalPotential = std::make_shared<IO::Variable>();
@ -93,7 +104,6 @@ void FreeEnergyAnalyzer::WriteVis( ScaLBL_FreeLeeModel &LeeModel, std::shared_pt
auto VyVar = std::make_shared<IO::Variable>();
auto VzVar = std::make_shared<IO::Variable>();
if (vis_db->getWithDefault<bool>("save_phase_field", true)) {
VisPhase->name = "Phase";
VisPhase->type = IO::VariableType::VolumeVariable;

View File

@ -53,10 +53,10 @@ public:
void SetParams();
void Basic(ScaLBL_FreeLeeModel &LeeModel, int timestep);
void WriteVis( ScaLBL_FreeLeeModel &LeeModel, std::shared_ptr<Database> input_db, int timestep);
void WriteVis(ScaLBL_FreeLeeModel &LeeModel,
std::shared_ptr<Database> input_db, int timestep);
private:
FILE *TIMELOG;
};
#endif

View File

@ -1,25 +1,35 @@
#include "analysis/GreyPhase.h"
// Constructor
GreyPhaseAnalysis::GreyPhaseAnalysis(std::shared_ptr <Domain> dm):
Dm(dm)
{
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0;
GreyPhaseAnalysis::GreyPhaseAnalysis(std::shared_ptr<Domain> dm) : Dm(dm) {
Nx = dm->Nx;
Ny = dm->Ny;
Nz = dm->Nz;
Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
Dm->nprocz() * 1.0;
// Global arrays
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
Porosity.resize(Nx,Ny,Nz); Porosity.fill(0);
SDs.resize(Nx, Ny, Nz);
SDs.fill(0);
Porosity.resize(Nx, Ny, Nz);
Porosity.fill(0);
//PhaseID.resize(Nx,Ny,Nz); PhaseID.fill(0);
Rho_n.resize(Nx,Ny,Nz); Rho_n.fill(0);
Rho_w.resize(Nx,Ny,Nz); Rho_w.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
Rho_n.resize(Nx, Ny, Nz);
Rho_n.fill(0);
Rho_w.resize(Nx, Ny, Nz);
Rho_w.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
//Phi.resize(Nx,Ny,Nz); Phi.fill(0);
//DelPhi.resize(Nx,Ny,Nz); DelPhi.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
MobilityRatio.resize(Nx,Ny,Nz); MobilityRatio.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
MobilityRatio.resize(Nx, Ny, Nz);
MobilityRatio.fill(0);
//.........................................
if (Dm->rank() == 0) {
@ -31,8 +41,7 @@ GreyPhaseAnalysis::GreyPhaseAnalysis(std::shared_ptr <Domain> dm):
WriteHeader = true;
TIMELOG = fopen("timelog.csv", "a+");
if (WriteHeader)
{
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG, "sw krw krn vw vn pw pn\n");
@ -40,20 +49,15 @@ GreyPhaseAnalysis::GreyPhaseAnalysis(std::shared_ptr <Domain> dm):
}
}
// Destructor
GreyPhaseAnalysis::~GreyPhaseAnalysis()
{
GreyPhaseAnalysis::~GreyPhaseAnalysis() {}
}
void GreyPhaseAnalysis::Write(int timestep) {}
void GreyPhaseAnalysis::Write(int timestep)
{
}
void GreyPhaseAnalysis::SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double B, double GreyPorosity)
{
void GreyPhaseAnalysis::SetParams(double rhoA, double rhoB, double tauA,
double tauB, double force_x, double force_y,
double force_z, double alpha, double B,
double GreyPorosity) {
Fx = force_x;
Fy = force_y;
Fz = force_z;
@ -70,10 +74,13 @@ void GreyPhaseAnalysis::Basic(){
int i, j, k, n, imin, jmin, kmin, kmax;
// If external boundary conditions are set, do not average over the inlet
kmin=1; kmax=Nz-1;
kmin = 1;
kmax = Nz - 1;
imin = jmin = 1;
if (Dm->inlet_layers_z > 0 && Dm->kproc() == 0) kmin += Dm->inlet_layers_z;
if (Dm->outlet_layers_z > 0 && Dm->kproc() == Dm->nprocz()-1) kmax -= Dm->outlet_layers_z;
if (Dm->inlet_layers_z > 0 && Dm->kproc() == 0)
kmin += Dm->inlet_layers_z;
if (Dm->outlet_layers_z > 0 && Dm->kproc() == Dm->nprocz() - 1)
kmax -= Dm->outlet_layers_z;
Water_local.reset();
Oil_local.reset();
@ -93,21 +100,26 @@ void GreyPhaseAnalysis::Basic(){
double mobility_ratio = MobilityRatio(n);
Water_local.M += nB * porosity;
Water_local.Px += porosity*(nA+nB)*Vel_x(n)*0.5*(1.0-mobility_ratio);
Water_local.Py += porosity*(nA+nB)*Vel_y(n)*0.5*(1.0-mobility_ratio);
Water_local.Pz += porosity*(nA+nB)*Vel_z(n)*0.5*(1.0-mobility_ratio);
Water_local.Px += porosity * (nA + nB) * Vel_x(n) * 0.5 *
(1.0 - mobility_ratio);
Water_local.Py += porosity * (nA + nB) * Vel_y(n) * 0.5 *
(1.0 - mobility_ratio);
Water_local.Pz += porosity * (nA + nB) * Vel_z(n) * 0.5 *
(1.0 - mobility_ratio);
Oil_local.M += nA * porosity;
Oil_local.Px += porosity*(nA+nB)*Vel_x(n)*0.5*(1.0+mobility_ratio);
Oil_local.Py += porosity*(nA+nB)*Vel_y(n)*0.5*(1.0+mobility_ratio);
Oil_local.Pz += porosity*(nA+nB)*Vel_z(n)*0.5*(1.0+mobility_ratio);
Oil_local.Px += porosity * (nA + nB) * Vel_x(n) * 0.5 *
(1.0 + mobility_ratio);
Oil_local.Py += porosity * (nA + nB) * Vel_y(n) * 0.5 *
(1.0 + mobility_ratio);
Oil_local.Pz += porosity * (nA + nB) * Vel_z(n) * 0.5 *
(1.0 + mobility_ratio);
if (phi > 0.99) {
Oil_local.p += Pressure(n);
//Oil_local.p += pressure*(rho_n*nA)/(rho_n*nA+rho_w*nB);
count_n += 1.0;
}
else if ( phi < -0.99 ){
} else if (phi < -0.99) {
Water_local.p += Pressure(n);
//Water_local.p += pressure*(rho_w*nB)/(rho_n*nA+rho_w*nB);
count_w += 1.0;
@ -126,7 +138,6 @@ void GreyPhaseAnalysis::Basic(){
Water.Py = Dm->Comm.sumReduce(Water_local.Py);
Water.Pz = Dm->Comm.sumReduce(Water_local.Pz);
//Oil.p /= Oil.M;
//Water.p /= Water.M;
count_w = Dm->Comm.sumReduce(count_w);
@ -142,17 +153,27 @@ void GreyPhaseAnalysis::Basic(){
// check for NaN
bool err = false;
if (Water.M != Water.M) err=true;
if (Water.p != Water.p) err=true;
if (Water.Px != Water.Px) err=true;
if (Water.Py != Water.Py) err=true;
if (Water.Pz != Water.Pz) err=true;
if (Water.M != Water.M)
err = true;
if (Water.p != Water.p)
err = true;
if (Water.Px != Water.Px)
err = true;
if (Water.Py != Water.Py)
err = true;
if (Water.Pz != Water.Pz)
err = true;
if (Oil.M != Oil.M) err=true;
if (Oil.p != Oil.p) err=true;
if (Oil.Px != Oil.Px) err=true;
if (Oil.Py != Oil.Py) err=true;
if (Oil.Pz != Oil.Pz) err=true;
if (Oil.M != Oil.M)
err = true;
if (Oil.p != Oil.p)
err = true;
if (Oil.Px != Oil.Px)
err = true;
if (Oil.Py != Oil.Py)
err = true;
if (Oil.Pz != Oil.Pz)
err = true;
if (Dm->rank() == 0) {
double force_mag = sqrt(Fx * Fx + Fy * Fy + Fz * Fz);
@ -163,14 +184,14 @@ void GreyPhaseAnalysis::Basic(){
dir_x = Fx / force_mag;
dir_y = Fy / force_mag;
dir_z = Fz / force_mag;
}
else {
} else {
// default to z direction
dir_x = 0.0;
dir_y = 0.0;
dir_z = 1.0;
}
if (Dm->BoundaryCondition == 1 || Dm->BoundaryCondition == 2 || Dm->BoundaryCondition == 3 || Dm->BoundaryCondition == 4 ){
if (Dm->BoundaryCondition == 1 || Dm->BoundaryCondition == 2 ||
Dm->BoundaryCondition == 3 || Dm->BoundaryCondition == 4) {
// compute the pressure drop
double pressure_drop = (Pressure(Nx * Ny + Nx + 1) - 1.0) / 3.0;
double length = ((Nz - 2) * Dm->nprocz());
@ -184,21 +205,28 @@ void GreyPhaseAnalysis::Basic(){
force_mag = 1.0;
}
saturation = Water.M / (Water.M + Oil.M); // assume constant density
water_flow_rate=grey_porosity*saturation*(Water.Px*dir_x + Water.Py*dir_y + Water.Pz*dir_z)/Water.M;
oil_flow_rate =grey_porosity*(1.0-saturation)*(Oil.Px*dir_x + Oil.Py*dir_y + Oil.Pz*dir_z)/Oil.M;
water_flow_rate =
grey_porosity * saturation *
(Water.Px * dir_x + Water.Py * dir_y + Water.Pz * dir_z) / Water.M;
oil_flow_rate = grey_porosity * (1.0 - saturation) *
(Oil.Px * dir_x + Oil.Py * dir_y + Oil.Pz * dir_z) /
Oil.M;
double h = Dm->voxel_length;
//TODO check if need greyporosity or domain porosity ? - compare to analytical solution
double krn = h * h * nu_n * oil_flow_rate / force_mag;
double krw = h * h * nu_w * water_flow_rate / force_mag;
//printf(" water saturation = %f, fractional flow =%f \n",saturation,fractional_flow);
fprintf(TIMELOG,"%.5g %.5g %.5g %.5g %.5g %.5g %.5g\n",saturation,krw,krn,h*water_flow_rate,h*oil_flow_rate, Water.p, Oil.p);
fprintf(TIMELOG, "%.5g %.5g %.5g %.5g %.5g %.5g %.5g\n", saturation,
krw, krn, h * water_flow_rate, h * oil_flow_rate, Water.p,
Oil.p);
fflush(TIMELOG);
}
if (err == true) {
// exception if simulation produceds NaN
printf("GreyPhaseAnalysis.cpp: NaN encountered, may need to check simulation parameters \n");
printf("GreyPhaseAnalysis.cpp: NaN encountered, may need to check "
"simulation parameters \n");
}
ASSERT(err == false);
}

View File

@ -15,7 +15,6 @@
#include "IO/Reader.h"
#include "IO/Writer.h"
/**
* \class GreyPhase
*
@ -27,14 +26,11 @@ class GreyPhase{
public:
double p;
double M, Px, Py, Pz;
void reset(){
p=M=Px=Py=Pz=0.0;
}
void reset() { p = M = Px = Py = Pz = 0.0; }
private:
};
/**
* \class GreyPhaseAnalysis
*
@ -76,7 +72,9 @@ public:
GreyPhaseAnalysis(std::shared_ptr<Domain> Dm);
~GreyPhaseAnalysis();
void SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double beta, double GreyPorosity);
void SetParams(double rhoA, double rhoB, double tauA, double tauB,
double force_x, double force_y, double force_z, double alpha,
double beta, double GreyPorosity);
void Basic();
void Write(int time);
@ -85,4 +83,3 @@ private:
};
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analysis/Minkowski.h"
#include "analysis/pmmc.h"
#include "analysis/analysis.h"
@ -13,25 +29,28 @@
#include <memory>
#define PI 3.14159265359
// Constructor
Minkowski::Minkowski(std::shared_ptr <Domain> dm):
kstart(0), kfinish(0), isovalue(0), Volume(0),
LOGFILE(NULL), Dm(dm), Vi(0), Vi_global(0)
{
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz;
Volume=double((Nx-2)*(Ny-2)*(Nz-2))*double(Dm->nprocx()*Dm->nprocy()*Dm->nprocz());
Minkowski::Minkowski(std::shared_ptr<Domain> dm)
: kstart(0), kfinish(0), isovalue(0), Volume(0), LOGFILE(NULL), Dm(dm),
Vi(0), Vi_global(0) {
Nx = dm->Nx;
Ny = dm->Ny;
Nz = dm->Nz;
Volume = double((Nx - 2) * (Ny - 2) * (Nz - 2)) *
double(Dm->nprocx() * Dm->nprocy() * Dm->nprocz());
id.resize(Nx,Ny,Nz); id.fill(0);
label.resize(Nx,Ny,Nz); label.fill(0);
distance.resize(Nx,Ny,Nz); distance.fill(0);
id.resize(Nx, Ny, Nz);
id.fill(0);
label.resize(Nx, Ny, Nz);
label.fill(0);
distance.resize(Nx, Ny, Nz);
distance.fill(0);
if (Dm->rank() == 0) {
LOGFILE = fopen("minkowski.csv", "a+");
if (fseek(LOGFILE,0,SEEK_SET) == fseek(LOGFILE,0,SEEK_CUR))
{
if (fseek(LOGFILE, 0, SEEK_SET) == fseek(LOGFILE, 0, SEEK_CUR)) {
// If LOGFILE is empty, write a short header to list the averages
//fprintf(LOGFILE,"--------------------------------------------------------------------------------------\n");
fprintf(LOGFILE, "Vn An Jn Xn\n"); //miknowski measures,
@ -39,15 +58,14 @@ Minkowski::Minkowski(std::shared_ptr <Domain> dm):
}
}
// Destructor
Minkowski::~Minkowski()
{
if ( LOGFILE!=NULL ) { fclose(LOGFILE); }
Minkowski::~Minkowski() {
if (LOGFILE != NULL) {
fclose(LOGFILE);
}
}
void Minkowski::ComputeScalar(const DoubleArray& Field, const double isovalue)
{
void Minkowski::ComputeScalar(const DoubleArray &Field, const double isovalue) {
PROFILE_START("ComputeScalar");
Xi = Ji = Ai = 0.0;
DCEL object;
@ -133,7 +151,6 @@ void Minkowski::ComputeScalar(const DoubleArray& Field, const double isovalue)
PROFILE_STOP("ComputeScalar");
}
void Minkowski::MeasureObject() {
/*
* compute the distance to an object
@ -156,7 +173,6 @@ void Minkowski::MeasureObject(){
ComputeScalar(distance, 0.0);
}
void Minkowski::MeasureObject(double factor, const DoubleArray &Phi) {
/*
* compute the distance to an object
@ -180,7 +196,8 @@ void Minkowski::MeasureObject(double factor, const DoubleArray &Phi){
double value = Phi(i, j, k);
double dist_value = distance(i, j, k);
if (dist_value < 2.5 && dist_value > -2.5) {
double new_distance = factor*log((1.0+value)/(1.0-value));
double new_distance =
factor * log((1.0 + value) / (1.0 - value));
if (dist_value * new_distance < 0.0)
new_distance = (-1.0) * new_distance;
distance(i, j, k) = new_distance;
@ -190,10 +207,8 @@ void Minkowski::MeasureObject(double factor, const DoubleArray &Phi){
}
ComputeScalar(distance, 0.0);
}
int Minkowski::MeasureConnectedPathway() {
/*
* compute the connected pathway for object with LABEL in id field
@ -209,8 +224,7 @@ int Minkowski::MeasureConnectedPathway(){
for (int i = 0; i < Nx; i++) {
if (id(i, j, k) == LABEL) {
distance(i, j, k) = 1.0;
}
else
} else
distance(i, j, k) = -1.0;
}
}
@ -218,7 +232,9 @@ int Minkowski::MeasureConnectedPathway(){
// Extract only the connected part of NWP
double vF = 0.0;
n_connected_components = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,Dm->rank_info,distance,distance,vF,vF,label,Dm->Comm);
n_connected_components =
ComputeGlobalBlobIDs(Nx - 2, Ny - 2, Nz - 2, Dm->rank_info, distance,
distance, vF, vF, label, Dm->Comm);
// int n_connected_components = ComputeGlobalPhaseComponent(Nx-2,Ny-2,Nz-2,Dm->rank_info,const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, Dm->Comm )
Dm->Comm.barrier();
@ -227,8 +243,7 @@ int Minkowski::MeasureConnectedPathway(){
for (int i = 0; i < Nx; i++) {
if (label(i, j, k) == 0) {
id(i, j, k) = 0;
}
else{
} else {
id(i, j, k) = 1;
}
}
@ -253,8 +268,7 @@ int Minkowski::MeasureConnectedPathway(double factor, const DoubleArray &Phi){
for (int i = 0; i < Nx; i++) {
if (id(i, j, k) == LABEL) {
distance(i, j, k) = 1.0;
}
else
} else
distance(i, j, k) = -1.0;
}
}
@ -262,18 +276,18 @@ int Minkowski::MeasureConnectedPathway(double factor, const DoubleArray &Phi){
// Extract only the connected part of NWP
double vF = 0.0;
n_connected_components = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,Dm->rank_info,distance,distance,vF,vF,label,Dm->Comm);
n_connected_components =
ComputeGlobalBlobIDs(Nx - 2, Ny - 2, Nz - 2, Dm->rank_info, distance,
distance, vF, vF, label, Dm->Comm);
// int n_connected_components = ComputeGlobalPhaseComponent(Nx-2,Ny-2,Nz-2,Dm->rank_info,const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, Dm->Comm )
Dm->Comm.barrier();
for (int k = 0; k < Nz; k++) {
for (int j = 0; j < Ny; j++) {
for (int i = 0; i < Nx; i++) {
if (label(i, j, k) == 0) {
id(i, j, k) = 0;
}
else{
} else {
id(i, j, k) = 1;
}
}
@ -283,12 +297,10 @@ int Minkowski::MeasureConnectedPathway(double factor, const DoubleArray &Phi){
return n_connected_components;
}
void Minkowski::PrintAll()
{
void Minkowski::PrintAll() {
if (Dm->rank() == 0) {
fprintf(LOGFILE,"%.5g %.5g %.5g %.5g\n",Vi_global, Ai_global, Ji_global, Xi_global); // minkowski measures
fprintf(LOGFILE, "%.5g %.5g %.5g %.5g\n", Vi_global, Ai_global,
Ji_global, Xi_global); // minkowski measures
fflush(LOGFILE);
}
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// Header file for two-phase averaging class
#ifndef Minkowski_INC
#define Minkowski_INC
@ -26,7 +42,6 @@
*
*/
class Minkowski {
//...........................................................................
int kstart, kfinish;
@ -54,18 +69,10 @@ public:
//...........................................................................
int Nx, Ny, Nz;
double V(){
return Vi;
}
double A(){
return Ai;
}
double H(){
return Ji;
}
double X(){
return Xi;
}
double V() { return Vi; }
double A() { return Ai; }
double H() { return Ji; }
double X() { return Xi; }
//..........................................................................
/**
@ -119,8 +126,6 @@ public:
* \brief print the scalar invariants
*/
void PrintAll();
};
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PointList_INC
#define PointList_INC
@ -10,20 +26,44 @@ struct LBPM_Point {
};
typedef LBPM_Point Point;
inline Point operator+(const Point &A,const Point &B) {return Point(A.x+B.x,A.y+B.y,A.z+B.z);}
inline Point operator-(const Point &A,const Point &B) {return Point(A.x-B.x,A.y-B.y,A.z-B.z);}
inline Point operator*(const Point &A,double v) {return Point(A.x*v,A.y*v,A.z*v);}
inline Point operator*(double v,const Point &A) {return Point(A.x*v,A.y*v,A.z*v);}
inline Point operator/(const Point &A,double v) {return Point(A.x/v,A.y/v,A.z/v);}
inline Point operator+(const Point &A, const Point &B) {
return Point(A.x + B.x, A.y + B.y, A.z + B.z);
}
inline Point operator-(const Point &A, const Point &B) {
return Point(A.x - B.x, A.y - B.y, A.z - B.z);
}
inline Point operator*(const Point &A, double v) {
return Point(A.x * v, A.y * v, A.z * v);
}
inline Point operator*(double v, const Point &A) {
return Point(A.x * v, A.y * v, A.z * v);
}
inline Point operator/(const Point &A, double v) {
return Point(A.x / v, A.y / v, A.z / v);
}
inline Point operator-(const Point &A) { return Point(-A.x, -A.y, -A.z); }
inline bool operator==(const Point &A,const Point &B) {return (A.x==B.x && A.y==B.y && A.z==B.z);}
inline bool operator!=(const Point &A,const Point &B) {return (A.x!=B.x || A.y!=B.y || A.z!=B.z);}
inline bool operator==(const Point &A, const Point &B) {
return (A.x == B.x && A.y == B.y && A.z == B.z);
}
inline bool operator!=(const Point &A, const Point &B) {
return (A.x != B.x || A.y != B.y || A.z != B.z);
}
inline double Norm(const Point &A) {return sqrt(A.x*A.x+A.y*A.y+A.z*A.z);}
inline Point Cross(const Point &A,const Point &B) {return Point(A.y*B.z-A.z*B.y,B.x*A.z-A.x*B.z,A.x*B.y-A.y*B.x);}
inline double Dot(const Point &A,const Point &B) {return (A.x*B.x+A.y*B.y+A.z*B.z);}
inline double Distance(const Point &A,const Point &B) {return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));}
inline double Norm(const Point &A) {
return sqrt(A.x * A.x + A.y * A.y + A.z * A.z);
}
inline Point Cross(const Point &A, const Point &B) {
return Point(A.y * B.z - A.z * B.y, B.x * A.z - A.x * B.z,
A.x * B.y - A.y * B.x);
}
inline double Dot(const Point &A, const Point &B) {
return (A.x * B.x + A.y * B.y + A.z * B.z);
}
inline double Distance(const Point &A, const Point &B) {
return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y) +
(A.z - B.z) * (A.z - B.z));
}
/*
class PointList{
@ -88,25 +128,38 @@ PointList::~PointList()
delete data;
}
*/
template <class T>
class DTList {
template <class T> class DTList {
public:
DTList() : Data(0), length(0), refCount(new size_t(1)), outOfRange() {}
DTList(const DTList<T> &A) : Data(A.Data), length(A.length), refCount(A.refCount), outOfRange() {++(*refCount);}
protected:
DTList(size_t len) : Data(len<=0 ? 0 : new T[len]), length(len<=0 ? 0 : len), refCount(new size_t(1)), outOfRange() {}
public:
DTList(const DTList<T> &A)
: Data(A.Data), length(A.length), refCount(A.refCount), outOfRange() {
++(*refCount);
}
protected:
DTList(size_t len)
: Data(len <= 0 ? 0 : new T[len]), length(len <= 0 ? 0 : len),
refCount(new size_t(1)), outOfRange() {}
public:
virtual ~DTList() {
--(*refCount);
if (*refCount==0) {delete [] Data; delete refCount;}
Data = 0; refCount = 0; length=0;
if (*refCount == 0) {
delete[] Data;
delete refCount;
}
Data = 0;
refCount = 0;
length = 0;
}
DTList<T> &operator=(const DTList<T> &A) {
if (A.refCount != refCount) { // Otherwise doing A=A.
--(*refCount);
if (*refCount==0) {delete [] Data; delete refCount;}
if (*refCount == 0) {
delete[] Data;
delete refCount;
}
refCount = A.refCount;
++(*refCount);
length = A.length;
@ -133,43 +186,50 @@ protected:
T outOfRange;
};
template <class T>
class DTMutableList : public DTList<T> {
template <class T> class DTMutableList : public DTList<T> {
public:
DTMutableList() : DTList<T>() {}
DTMutableList(size_t len) : DTList<T>(len) {}
DTMutableList(const DTMutableList<T> &A) : DTList<T>(A) {}
DTMutableList<T> &operator=(const DTMutableList<T> &A) {DTList<T>::operator=(A); return *this;}
DTMutableList<T> &operator=(const DTMutableList<T> &A) {
DTList<T>::operator=(A);
return *this;
}
T *Pointer(void) { return DTList<T>::Data; }
const T *Pointer(void) const { return DTList<T>::Data; }
T &operator()(size_t i) { return DTList<T>::Data[i]; }
T operator()(size_t i) const { return DTList<T>::Data[i]; }
DTMutableList<T> &operator=(T v) {for (size_t i=0;i<DTList<T>::length;i++) DTList<T>::Data[i] = v; return *this;}
DTMutableList<T> &operator=(T v) {
for (size_t i = 0; i < DTList<T>::length; i++)
DTList<T>::Data[i] = v;
return *this;
}
};
template <class T> DTMutableList<T> TruncateSize(const DTList<T> &A,size_t length)
{
if (length>A.Length()) length = A.Length();
template <class T>
DTMutableList<T> TruncateSize(const DTList<T> &A, size_t length) {
if (length > A.Length())
length = A.Length();
DTMutableList<T> toReturn(length);
const T *fromP = A.Pointer();
T *toP = toReturn.Pointer();
for (size_t i=0;i<length;i++) toP[i] = fromP[i];
for (size_t i = 0; i < length; i++)
toP[i] = fromP[i];
return toReturn;
}
template <class T> DTMutableList<T> IncreaseSize(const DTList<T> &A,size_t addLength)
{
template <class T>
DTMutableList<T> IncreaseSize(const DTList<T> &A, size_t addLength) {
DTMutableList<T> toReturn(A.Length() + (addLength >= 0 ? addLength : 0));
size_t len = A.Length();
const T *fromP = A.Pointer();
T *toP = toReturn.Pointer();
for (size_t i=0;i<len;i++) toP[i] = fromP[i];
for (size_t i = 0; i < len; i++)
toP[i] = fromP[i];
return toReturn;
}
#endif

View File

@ -1,30 +1,44 @@
#include "analysis/SubPhase.h"
// Constructor
SubPhase::SubPhase(std::shared_ptr <Domain> dm):
Dm(dm)
{
Nx=dm->Nx; Ny=dm->Ny; Nz=dm->Nz;
Volume=(Nx-2)*(Ny-2)*(Nz-2)*Dm->nprocx()*Dm->nprocy()*Dm->nprocz()*1.0;
SubPhase::SubPhase(std::shared_ptr<Domain> dm) : Dm(dm) {
Nx = dm->Nx;
Ny = dm->Ny;
Nz = dm->Nz;
Volume = (Nx - 2) * (Ny - 2) * (Nz - 2) * Dm->nprocx() * Dm->nprocy() *
Dm->nprocz() * 1.0;
morph_w = std::shared_ptr<Minkowski>(new Minkowski(Dm));
morph_n = std::shared_ptr<Minkowski>(new Minkowski(Dm));
morph_i = std::shared_ptr<Minkowski>(new Minkowski(Dm));
// Global arrays
PhaseID.resize(Nx,Ny,Nz); PhaseID.fill(0);
Label_WP.resize(Nx,Ny,Nz); Label_WP.fill(0);
Label_NWP.resize(Nx,Ny,Nz); Label_NWP.fill(0);
Rho_n.resize(Nx,Ny,Nz); Rho_n.fill(0);
Rho_w.resize(Nx,Ny,Nz); Rho_w.fill(0);
Pressure.resize(Nx,Ny,Nz); Pressure.fill(0);
Phi.resize(Nx,Ny,Nz); Phi.fill(0);
DelPhi.resize(Nx,Ny,Nz); DelPhi.fill(0);
Vel_x.resize(Nx,Ny,Nz); Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx,Ny,Nz); Vel_y.fill(0);
Vel_z.resize(Nx,Ny,Nz); Vel_z.fill(0);
Dissipation.resize(Nx,Ny,Nz); Dissipation.fill(0);
SDs.resize(Nx,Ny,Nz); SDs.fill(0);
PhaseID.resize(Nx, Ny, Nz);
PhaseID.fill(0);
Label_WP.resize(Nx, Ny, Nz);
Label_WP.fill(0);
Label_NWP.resize(Nx, Ny, Nz);
Label_NWP.fill(0);
Rho_n.resize(Nx, Ny, Nz);
Rho_n.fill(0);
Rho_w.resize(Nx, Ny, Nz);
Rho_w.fill(0);
Pressure.resize(Nx, Ny, Nz);
Pressure.fill(0);
Phi.resize(Nx, Ny, Nz);
Phi.fill(0);
DelPhi.resize(Nx, Ny, Nz);
DelPhi.fill(0);
Vel_x.resize(Nx, Ny, Nz);
Vel_x.fill(0); // Gradient of the phase indicator field
Vel_y.resize(Nx, Ny, Nz);
Vel_y.fill(0);
Vel_z.resize(Nx, Ny, Nz);
Vel_z.fill(0);
Dissipation.resize(Nx, Ny, Nz);
Dissipation.fill(0);
SDs.resize(Nx, Ny, Nz);
SDs.fill(0);
//.........................................
//.........................................
@ -37,16 +51,18 @@ SubPhase::SubPhase(std::shared_ptr <Domain> dm):
WriteHeader = true;
SUBPHASE = fopen("subphase.csv", "a+");
if (WriteHeader)
{
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(SUBPHASE,"--------------------------------------------------------------------------------------\n");
fprintf(SUBPHASE, "time rn rw nun nuw Fx Fy Fz iftwn wet ");
fprintf(SUBPHASE, "pwc pwd pnc pnd "); // pressures
fprintf(SUBPHASE, "Mwc Mwd Mwi Mnc Mnd Mni Msw Msn "); // mass
fprintf(SUBPHASE,"Pwc_x Pwd_x Pwi_x Pnc_x Pnd_x Pni_x Psw_x Psn_x "); // momentum
fprintf(SUBPHASE,"Pwc_y Pwd_y Pwi_y Pnc_y Pnd_y Pni_y Psw_y Psn_y ");
fprintf(SUBPHASE,"Pwc_z Pwd_z Pwi_z Pnc_z Pnd_z Pni_z Psw_z Psn_z ");
fprintf(
SUBPHASE,
"Pwc_x Pwd_x Pwi_x Pnc_x Pnd_x Pni_x Psw_x Psn_x "); // momentum
fprintf(SUBPHASE,
"Pwc_y Pwd_y Pwi_y Pnc_y Pnd_y Pni_y Psw_y Psn_y ");
fprintf(SUBPHASE,
"Pwc_z Pwd_z Pwi_z Pnc_z Pnd_z Pni_z Psw_z Psn_z ");
fprintf(SUBPHASE, "Kwc Kwd Kwi Knc Knd Kni "); // kinetic energy
fprintf(SUBPHASE, "Dwc Dwd Dnc Dnd "); // viscous dissipation
fprintf(SUBPHASE, "Vwc Awc Hwc Xwc "); // wc region
@ -59,18 +75,18 @@ SubPhase::SubPhase(std::shared_ptr <Domain> dm):
// stress tensor?
}
}
else{
} else {
char LocalRankString[8];
sprintf(LocalRankString, "%05d", Dm->rank());
char LocalRankFilename[40];
sprintf(LocalRankFilename, "%s%s", "subphase.csv.", LocalRankString);
SUBPHASE = fopen(LocalRankFilename, "a+");
//fprintf(SUBPHASE,"--------------------------------------------------------------------------------------\n");
fprintf(SUBPHASE, "time rn rw nun nuw Fx Fy Fz iftwn wet ");
fprintf(SUBPHASE, "pwc pwd pnc pnd "); // pressures
fprintf(SUBPHASE, "Mwc Mwd Mwi Mnc Mnd Mni Msw Msn "); // mass
fprintf(SUBPHASE,"Pwc_x Pwd_x Pwi_x Pnc_x Pnd_x Pni_x Psw_x Psn_x "); // momentum
fprintf(SUBPHASE,
"Pwc_x Pwd_x Pwi_x Pnc_x Pnd_x Pni_x Psw_x Psn_x "); // momentum
fprintf(SUBPHASE, "Pwc_y Pwd_y Pwi_y Pnc_y Pnd_y Pni_y Psw_y Psn_y ");
fprintf(SUBPHASE, "Pwc_z Pwd_z Pwi_z Pnc_z Pnd_z Pni_z Psw_z Psn_z ");
fprintf(SUBPHASE, "Kwc Kwd Kwi Knc Knd Kni "); // kinetic energy
@ -92,63 +108,82 @@ SubPhase::SubPhase(std::shared_ptr <Domain> dm):
WriteHeader = true;
TIMELOG = fopen("timelog.csv", "a+");
if (WriteHeader)
{
if (WriteHeader) {
// If timelog is empty, write a short header to list the averages
//fprintf(TIMELOG,"--------------------------------------------------------------------------------------\n");
fprintf(TIMELOG,"sw krw krn krwf krnf vw vn force pw pn wet\n");
fprintf(TIMELOG,
"sw krw krn krwf krnf vw vn force pw pn wet peff\n");
}
}
}
// Destructor
SubPhase::~SubPhase()
{
if ( SUBPHASE!=NULL ) { fclose(SUBPHASE); }
SubPhase::~SubPhase() {
if (SUBPHASE != NULL) {
fclose(SUBPHASE);
}
}
void SubPhase::Write(int timestep)
{
void SubPhase::Write(int timestep) {
if (Dm->rank() == 0) {
fprintf(SUBPHASE,"%i %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",timestep,rho_n,rho_w,nu_n,nu_w,Fx,Fy,Fz,gamma_wn,total_wetting_interaction_global);
fprintf(SUBPHASE, "%i %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",
timestep, rho_n, rho_w, nu_n, nu_w, Fx, Fy, Fz, gamma_wn,
total_wetting_interaction_global);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", gwc.p, gwd.p, gnc.p, gnd.p);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",gwc.M, gwd.M, giwn.Mw, gnc.M, gnd.M, giwn.Mn, gifs.Mw, gifs.Mn);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",gwc.Px, gwd.Px, giwn.Pwx, gnc.Px, gnd.Px, giwn.Pnx, gifs.Pwx, gifs.Pnx);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",gwc.Py, gwd.Py, giwn.Pwy, gnc.Py, gnd.Py, giwn.Pny, gifs.Pwy, gifs.Pny);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",gwc.Pz, gwd.Pz, giwn.Pwz, gnc.Pz, gnd.Pz, giwn.Pnz, gifs.Pwz, gifs.Pnz);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g ",gwc.K, gwd.K, giwn.Kw, gnc.K, gnd.K, giwn.Kn);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g ",gwc.visc, gwd.visc, gnc.visc, gnd.visc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", gwc.M,
gwd.M, giwn.Mw, gnc.M, gnd.M, giwn.Mn, gifs.Mw, gifs.Mn);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", gwc.Px,
gwd.Px, giwn.Pwx, gnc.Px, gnd.Px, giwn.Pnx, gifs.Pwx, gifs.Pnx);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", gwc.Py,
gwd.Py, giwn.Pwy, gnc.Py, gnd.Py, giwn.Pny, gifs.Pwy, gifs.Pny);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", gwc.Pz,
gwd.Pz, giwn.Pwz, gnc.Pz, gnd.Pz, giwn.Pnz, gifs.Pwz, gifs.Pnz);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g ", gwc.K, gwd.K,
giwn.Kw, gnc.K, gnd.K, giwn.Kn);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", gwc.visc, gwd.visc, gnc.visc,
gnd.visc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", gwc.V, gwc.A, gwc.H, gwc.X);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %i ",gwd.V, gwd.A, gwd.H, gwd.X, gwd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %i ", gwd.V, gwd.A, gwd.H, gwd.X,
gwd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", gnc.V, gnc.A, gnc.H, gnc.X);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %i ",gnd.V, gnd.A, gnd.H, gnd.X, gnd.Nc);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g ",giwn.V, giwn.A, giwn.H, giwn.X);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %i\n",giwnc.V, giwnc.A, giwnc.H, giwnc.X, giwnc.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %i ", gnd.V, gnd.A, gnd.H, gnd.X,
gnd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", giwn.V, giwn.A, giwn.H,
giwn.X);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %i\n", giwnc.V, giwnc.A, giwnc.H,
giwnc.X, giwnc.Nc);
fflush(SUBPHASE);
}
else{
fprintf(SUBPHASE,"%i %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",timestep,rho_n,rho_w,nu_n,nu_w,Fx,Fy,Fz,gamma_wn,total_wetting_interaction);
} else {
fprintf(SUBPHASE, "%i %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",
timestep, rho_n, rho_w, nu_n, nu_w, Fx, Fy, Fz, gamma_wn,
total_wetting_interaction);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", wc.p, wd.p, nc.p, nd.p);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",wc.M, wd.M, iwn.Mw, nc.M, nd.M, iwn.Mn, ifs.Mw, ifs.Mn);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",wc.Px, wd.Px, iwn.Pwx, nc.Px, nd.Px, iwn.Pnx, ifs.Pwx, ifs.Pnx);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",wc.Py, wd.Py, iwn.Pwy, nc.Py, nd.Py, iwn.Pny, ifs.Pwy, ifs.Pny);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ",wc.Pz, wd.Pz, iwn.Pwz, nc.Pz, nd.Pz, iwn.Pnz, ifs.Pwz, ifs.Pnz);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %.8g %.8g ",wc.K, wd.K, iwn.Kw, nc.K, nd.K, iwn.Kn);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g ",wc.visc, wd.visc, nc.visc, nd.visc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", wc.M,
wd.M, iwn.Mw, nc.M, nd.M, iwn.Mn, ifs.Mw, ifs.Mn);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", wc.Px,
wd.Px, iwn.Pwx, nc.Px, nd.Px, iwn.Pnx, ifs.Pwx, ifs.Pnx);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", wc.Py,
wd.Py, iwn.Pwy, nc.Py, nd.Py, iwn.Pny, ifs.Pwy, ifs.Pny);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g ", wc.Pz,
wd.Pz, iwn.Pwz, nc.Pz, nd.Pz, iwn.Pnz, ifs.Pwz, ifs.Pnz);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %.8g %.8g ", wc.K, wd.K, iwn.Kw,
nc.K, nd.K, iwn.Kn);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", wc.visc, wd.visc, nc.visc,
nd.visc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", wc.V, wc.A, wc.H, wc.X);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %i ",wd.V, wd.A, wd.H, wd.X, wd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %i ", wd.V, wd.A, wd.H, wd.X,
wd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", nc.V, nc.A, nc.H, nc.X);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g %i ",nd.V, nd.A, nd.H, nd.X, nd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g %i ", nd.V, nd.A, nd.H, nd.X,
nd.Nc);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g ", iwn.V, iwn.A, iwn.H, iwn.X);
fprintf(SUBPHASE,"%.8g %.8g %.8g %.8g\n",iwnc.V, iwnc.A, iwnc.H, iwnc.X);
fprintf(SUBPHASE, "%.8g %.8g %.8g %.8g\n", iwnc.V, iwnc.A, iwnc.H,
iwnc.X);
}
}
}
void SubPhase::SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double B)
{
void SubPhase::SetParams(double rhoA, double rhoB, double tauA, double tauB,
double force_x, double force_y, double force_z,
double alpha, double B) {
Fx = force_x;
Fy = force_y;
Fz = force_z;
@ -164,15 +199,13 @@ void SubPhase::Basic(){
int i, j, k, n, imin, jmin, kmin, kmax;
// If external boundary conditions are set, do not average over the inlet
kmin=1; kmax=Nz-1;
kmin = 1;
kmax = Nz - 1;
imin = jmin = 1;
/*// If inlet/outlet layers exist use these as default
if (Dm->inlet_layers_x > 0) imin = Dm->inlet_layers_x;
if (Dm->inlet_layers_y > 0) jmin = Dm->inlet_layers_y;
if (Dm->inlet_layers_z > 0 && Dm->kproc() == 0) kmin += Dm->inlet_layers_z;
if (Dm->outlet_layers_z > 0 && Dm->kproc() == Dm->nprocz()-1) kmax -= Dm->outlet_layers_z;
*/
nb.reset(); wb.reset(); iwn.reset();
nb.reset();
wb.reset();
iwn.reset();
double count_w = 0.0;
double count_n = 0.0;
@ -231,8 +264,7 @@ void SubPhase::Basic(){
nb.Px += rho_n * nA * Vel_x(n);
nb.Py += rho_n * nA * Vel_y(n);
nb.Pz += rho_n * nA * Vel_z(n);
}
else{
} else {
nB = 1.0;
wb.M += nB * rho_w;
wb.V += 1.0;
@ -245,8 +277,7 @@ void SubPhase::Basic(){
if (phi > 0.99) {
nb.p += Pressure(n);
count_n += 1.0;
}
else if ( phi < -0.99 ){
} else if (phi < -0.99) {
wb.p += Pressure(n);
count_w += 1.0;
}
@ -260,8 +291,7 @@ void SubPhase::Basic(){
iwn.Pnx += rho_n * nA * Vel_x(n);
iwn.Pny += rho_n * nA * Vel_y(n);
iwn.Pnz += rho_n * nA * Vel_z(n);
}
else{
} else {
nB = 1.0;
iwn.Mw += nB * rho_w;
iwn.V += 1.0;
@ -290,9 +320,11 @@ void SubPhase::Basic(){
}
}
}
//printf("wetting interaction = %f, count = %f\n",total_wetting_interaction,count_wetting_interaction);
total_wetting_interaction_global=Dm->Comm.sumReduce( total_wetting_interaction);
count_wetting_interaction_global=Dm->Comm.sumReduce( count_wetting_interaction);
total_wetting_interaction_global =
Dm->Comm.sumReduce(total_wetting_interaction);
count_wetting_interaction_global =
Dm->Comm.sumReduce(count_wetting_interaction);
gwb.V = Dm->Comm.sumReduce(wb.V);
gnb.V = Dm->Comm.sumReduce(nb.V);
@ -328,16 +360,26 @@ void SubPhase::Basic(){
// check for NaN
bool err = false;
if (gwb.V != gwb.V) err=true;
if (gnb.V != gnb.V) err=true;
if (gwb.p != gwb.p) err=true;
if (gnb.p != gnb.p) err=true;
if (gwb.Px != gwb.Px) err=true;
if (gwb.Py != gwb.Py) err=true;
if (gwb.Pz != gwb.Pz) err=true;
if (gnb.Px != gnb.Px) err=true;
if (gnb.Py != gnb.Py) err=true;
if (gnb.Pz != gnb.Pz) err=true;
if (gwb.V != gwb.V)
err = true;
if (gnb.V != gnb.V)
err = true;
if (gwb.p != gwb.p)
err = true;
if (gnb.p != gnb.p)
err = true;
if (gwb.Px != gwb.Px)
err = true;
if (gwb.Py != gwb.Py)
err = true;
if (gwb.Pz != gwb.Pz)
err = true;
if (gnb.Px != gnb.Px)
err = true;
if (gnb.Py != gnb.Py)
err = true;
if (gnb.Pz != gnb.Pz)
err = true;
if (Dm->rank() == 0) {
/* align flow direction based on total mass flux */
@ -350,13 +392,13 @@ void SubPhase::Basic(){
dir_x = Fx / force_mag;
dir_y = Fy / force_mag;
dir_z = Fz / force_mag;
}
else {
} else {
dir_x /= flow_magnitude;
dir_y /= flow_magnitude;
dir_z /= flow_magnitude;
}
if (Dm->BoundaryCondition == 1 || Dm->BoundaryCondition == 2 || Dm->BoundaryCondition == 3 || Dm->BoundaryCondition == 4 ){
if (Dm->BoundaryCondition == 1 || Dm->BoundaryCondition == 2 ||
Dm->BoundaryCondition == 3 || Dm->BoundaryCondition == 4) {
// compute the pressure drop
double pressure_drop = (Pressure(Nx * Ny + Nx + 1) - 1.0) / 3.0;
double length = ((Nz - 2) * Dm->nprocz());
@ -370,34 +412,49 @@ void SubPhase::Basic(){
force_mag = 1.0;
}
double saturation = gwb.V / (gwb.V + gnb.V);
double water_flow_rate=gwb.V*(gwb.Px*dir_x + gwb.Py*dir_y + gwb.Pz*dir_z)/gwb.M / Dm->Volume;
double not_water_flow_rate=gnb.V*(gnb.Px*dir_x + gnb.Py*dir_y + gnb.Pz*dir_z)/gnb.M/ Dm->Volume;
double water_flow_rate =
gwb.V * (gwb.Px * dir_x + gwb.Py * dir_y + gwb.Pz * dir_z) / gwb.M /
Dm->Volume;
double not_water_flow_rate =
gnb.V * (gnb.Px * dir_x + gnb.Py * dir_y + gnb.Pz * dir_z) / gnb.M /
Dm->Volume;
/* contribution from water films */
double water_film_flow_rate=gwb.V*(giwn.Pwx*dir_x + giwn.Pwy*dir_y + giwn.Pwz*dir_z)/gwb.M / Dm->Volume;
double not_water_film_flow_rate=gnb.V*(giwn.Pnx*dir_x + giwn.Pny*dir_y + giwn.Pnz*dir_z)/gnb.M / Dm->Volume;
double water_film_flow_rate =
gwb.V * (giwn.Pwx * dir_x + giwn.Pwy * dir_y + giwn.Pwz * dir_z) /
gwb.M / Dm->Volume;
double not_water_film_flow_rate =
gnb.V * (giwn.Pnx * dir_x + giwn.Pny * dir_y + giwn.Pnz * dir_z) /
gnb.M / Dm->Volume;
//double total_flow_rate = water_flow_rate + not_water_flow_rate;
//double fractional_flow = water_flow_rate / total_flow_rate;
double h = Dm->voxel_length;
double krn = h * h * nu_n * not_water_flow_rate / force_mag;
double krw = h * h * nu_w * water_flow_rate / force_mag;
/* not counting films */
double krnf = krn - h * h * nu_n * not_water_film_flow_rate / force_mag;
double krwf = krw - h * h * nu_w * water_film_flow_rate / force_mag;
//printf(" water saturation = %f, fractional flow =%f \n",saturation,fractional_flow);
fprintf(TIMELOG,"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g\n",saturation,krw,krn,krwf,krnf,h*water_flow_rate,h*not_water_flow_rate, force_mag, gwb.p, gnb.p, total_wetting_interaction_global);
double eff_pressure = 1.0 / (krn + krw); // effective pressure drop
fprintf(TIMELOG,
"%.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g %.8g\n",
saturation, krw, krn, krwf, krnf, h * water_flow_rate,
h * not_water_flow_rate, force_mag, gwb.p, gnb.p,
total_wetting_interaction_global, eff_pressure);
fflush(TIMELOG);
}
if (err == true) {
// exception if simulation produceds NaN
printf("SubPhase.cpp: NaN encountered, may need to check simulation parameters \n");
printf("SubPhase.cpp: NaN encountered, may need to check simulation "
"parameters \n");
}
ASSERT(err == false);
}
inline void InterfaceTransportMeasures( double beta, double rA, double rB, double nA, double nB,
double nx, double ny, double nz, double ux, double uy, double uz, interface &I){
inline void InterfaceTransportMeasures(double beta, double rA, double rB,
double nA, double nB, double nx,
double ny, double nz, double ux,
double uy, double uz, interface &I) {
double A1, A2, A3, A4, A5, A6;
double B1, B2, B3, B4, B5, B6;
@ -410,7 +467,8 @@ inline void InterfaceTransportMeasures( double beta, double rA, double rB, doubl
// q = 0,2,4
// Cq = {1,0,0}, {0,1,0}, {0,0,1}
delta = beta * nA * nB * nAB * 0.1111111111111111 * nx;
if (!(nA*nB*nAB>0)) delta=0;
if (!(nA * nB * nAB > 0))
delta = 0;
A1 = nA * (0.1111111111111111 * (1 + 4.5 * ux)) + delta;
B1 = nB * (0.1111111111111111 * (1 + 4.5 * ux)) - delta;
A2 = nA * (0.1111111111111111 * (1 - 4.5 * ux)) - delta;
@ -419,7 +477,8 @@ inline void InterfaceTransportMeasures( double beta, double rA, double rB, doubl
//...............................................
// Cq = {0,1,0}
delta = beta * nA * nB * nAB * 0.1111111111111111 * ny;
if (!(nA*nB*nAB>0)) delta=0;
if (!(nA * nB * nAB > 0))
delta = 0;
A3 = nA * (0.1111111111111111 * (1 + 4.5 * uy)) + delta;
B3 = nB * (0.1111111111111111 * (1 + 4.5 * uy)) - delta;
A4 = nA * (0.1111111111111111 * (1 - 4.5 * uy)) - delta;
@ -429,7 +488,8 @@ inline void InterfaceTransportMeasures( double beta, double rA, double rB, doubl
// q = 4
// Cq = {0,0,1}
delta = beta * nA * nB * nAB * 0.1111111111111111 * nz;
if (!(nA*nB*nAB>0)) delta=0;
if (!(nA * nB * nAB > 0))
delta = 0;
A5 = nA * (0.1111111111111111 * (1 + 4.5 * uz)) + delta;
B5 = nB * (0.1111111111111111 * (1 + 4.5 * uz)) - delta;
A6 = nA * (0.1111111111111111 * (1 - 4.5 * uz)) - delta;
@ -458,8 +518,7 @@ inline void InterfaceTransportMeasures( double beta, double rA, double rB, doubl
I.Pnx += rA * ux;
I.Pny += rA * uy;
I.Pnz += rA * uz;
}
else {
} else {
I.Mw += rB;
I.Pwx += rB * ux;
I.Pwy += rB * uy;
@ -467,26 +526,23 @@ inline void InterfaceTransportMeasures( double beta, double rA, double rB, doubl
}
I.Kn += rA * nA * (unx * unx + uny * uny + unz * unz);
I.Kw += rB * nB * (uwx * uwx + uwy * uwy + uwz * uwz);
}
void SubPhase::Full() {
int i, j, k, n, imin, jmin, kmin, kmax;
// If external boundary conditions are set, do not average over the inlet
kmin=1; kmax=Nz-1;
/*if (Dm->BoundaryCondition > 0 && Dm->BoundaryCondition != 5 && Dm->kproc() == 0) kmin=4;
if (Dm->BoundaryCondition > 0 && Dm->BoundaryCondition != 5 && Dm->kproc() == Dm->nprocz()-1) kmax=Nz-4;
*/
kmin = 1;
kmax = Nz - 1;
imin = jmin = 1;
/*// If inlet layers exist use these as default
* NOTE -- excluding inlet / outlet will screw up topological averages!!!
if (Dm->inlet_layers_x > 0) imin = Dm->inlet_layers_x;
if (Dm->inlet_layers_y > 0) jmin = Dm->inlet_layers_y;
if (Dm->inlet_layers_z > 0 && Dm->kproc() == 0) kmin += Dm->inlet_layers_z;
if (Dm->outlet_layers_z > 0 && Dm->kproc() == Dm->nprocz()-1) kmax -= Dm->outlet_layers_z;
*/
nd.reset(); nc.reset(); wd.reset(); wc.reset(); iwn.reset(); iwnc.reset(); ifs.reset();
nd.reset();
nc.reset();
wd.reset();
wc.reset();
iwn.reset();
iwnc.reset();
ifs.reset();
Dm->CommunicateMeshHalo(Phi);
for (int k = 1; k < Nz - 1; k++) {
@ -502,7 +558,6 @@ void SubPhase::Full(){
}
Dm->CommunicateMeshHalo(DelPhi);
Dm->CommunicateMeshHalo(Vel_x);
Dm->CommunicateMeshHalo(Vel_y);
Dm->CommunicateMeshHalo(Vel_z);
@ -523,7 +578,11 @@ void SubPhase::Full(){
double wy = 0.5 * (Vel_z(i, j + 1, k) - Vel_z(i, j - 1, k));
double wz = 0.5 * (Vel_z(i, j, k + 1) - Vel_z(i, j, k - 1));
if (SDs(i, j, k) > 2.0) {
Dissipation(i,j,k) = 2*rho*nu*( ux*ux + vy*vy + wz*wz + 0.5*(vx + uy)*(vx + uy)+ 0.5*(vz + wy)*(vz + wy)+ 0.5*(uz + wx)*(uz + wx));
Dissipation(i, j, k) = 2 * rho * nu *
(ux * ux + vy * vy + wz * wz +
0.5 * (vx + uy) * (vx + uy) +
0.5 * (vz + wy) * (vz + wy) +
0.5 * (uz + wx) * (uz + wx));
}
}
}
@ -540,12 +599,10 @@ void SubPhase::Full(){
// Solid phase
morph_n->id(i, j, k) = 1;
}
else if (Phi(n) > 0.0){
} else if (Phi(n) > 0.0) {
// non-wetting phase
morph_n->id(i, j, k) = 0;
}
else {
} else {
// wetting phase
morph_n->id(i, j, k) = 1;
}
@ -589,12 +646,10 @@ void SubPhase::Full(){
// Solid phase
morph_w->id(i, j, k) = 1;
}
else if (Phi(n) < 0.0){
} else if (Phi(n) < 0.0) {
// wetting phase
morph_w->id(i, j, k) = 0;
}
else {
} else {
// non-wetting phase
morph_w->id(i, j, k) = 1;
}
@ -636,12 +691,10 @@ void SubPhase::Full(){
if (!(Dm->id[n] > 0)) {
// Solid phase
morph_i->id(i, j, k) = 1;
}
else if (DelPhi(n) > 1e-4){
} else if (DelPhi(n) > 1e-4) {
// interface
morph_i->id(i, j, k) = 0;
}
else {
} else {
// not interface
morph_i->id(i, j, k) = 1;
}
@ -695,9 +748,10 @@ void SubPhase::Full(){
double nz = 0.5 * (Phi(i, j, k + 1) - Phi(i, j, k - 1));
if (SDs(n) > 2.5) {
// not a film region
InterfaceTransportMeasures( beta, rho_w, rho_n, nA, nB, nx, ny, nz, ux, uy, uz, iwn);
}
else{
InterfaceTransportMeasures(beta, rho_w, rho_n, nA,
nB, nx, ny, nz, ux, uy,
uz, iwn);
} else {
// films that are close to the wetting fluid
if (morph_w->distance(i, j, k) < 2.5 && phi > 0.0) {
ifs.Mw += rho_w;
@ -713,24 +767,20 @@ void SubPhase::Full(){
ifs.Pnz += rho_n * uz;
}
}
}
else if ( phi > 0.0){
} else if (phi > 0.0) {
if (morph_n->label(i, j, k) > 0) {
vol_nd_bulk += 1.0;
nd.p += Pressure(n);
}
else{
} else {
vol_nc_bulk += 1.0;
nc.p += Pressure(n);
}
}
else{
} else {
// water region
if (morph_w->label(i, j, k) > 0) {
vol_wd_bulk += 1.0;
wd.p += Pressure(n);
}
else{
} else {
vol_wc_bulk += 1.0;
wc.p += Pressure(n);
}
@ -744,8 +794,7 @@ void SubPhase::Full(){
nd.Pz += nA * rho_n * uz;
nd.K += nA * rho_n * (ux * ux + uy * uy + uz * uz);
nd.visc += visc;
}
else{
} else {
nA = 1.0;
nc.M += nA * rho_n;
nc.Px += nA * rho_n * ux;
@ -754,8 +803,7 @@ void SubPhase::Full(){
nc.K += nA * rho_n * (ux * ux + uy * uy + uz * uz);
nc.visc += visc;
}
}
else{
} else {
// water region
if (morph_w->label(i, j, k) > 0) {
nB = 1.0;
@ -765,8 +813,7 @@ void SubPhase::Full(){
wd.Pz += nB * rho_w * uz;
wd.K += nB * rho_w * (ux * ux + uy * uy + uz * uz);
wd.visc += visc;
}
else{
} else {
nB = 1.0;
wc.M += nB * rho_w;
wc.Px += nB * rho_w * ux;
@ -859,15 +906,12 @@ void SubPhase::Full(){
gnd.p = gnd.p / vol_nd_bulk;
}
void SubPhase::AggregateLabels( const std::string& filename )
{
void SubPhase::AggregateLabels(const std::string &filename) {
int nx = Dm->Nx;
int ny = Dm->Ny;
int nz = Dm->Nz;
//printf("aggregate labels: local size=%i, global size = %i",local_size, full_size);
// assign the ID from the phase indicator field
for (int k = 0; k < nz; k++) {
for (int j = 0; j < ny; j++) {
@ -876,8 +920,10 @@ void SubPhase::AggregateLabels( const std::string& filename )
signed char local_id_val = Dm->id[n];
if (local_id_val > 0) {
double value = Phi(i, j, k);
if (value > 0.0) local_id_val = 1;
else local_id_val = 2;
if (value > 0.0)
local_id_val = 1;
else
local_id_val = 2;
}
Dm->id[n] = local_id_val;
}
@ -886,8 +932,4 @@ void SubPhase::AggregateLabels( const std::string& filename )
Dm->Comm.barrier();
Dm->AggregateLabels(filename);
}

View File

@ -17,7 +17,6 @@
#include "IO/Reader.h"
#include "IO/Writer.h"
class phase {
public:
int Nc;
@ -86,7 +85,8 @@ public:
IntArray PhaseID; // Phase ID array (solid=0, non-wetting=1, wetting=2)
BlobIDArray Label_WP; // Wetting phase label
BlobIDArray Label_NWP; // Non-wetting phase label index (0:nblobs-1)
std::vector<BlobIDType> Label_NWP_map; // Non-wetting phase label for each index
std::vector<BlobIDType>
Label_NWP_map; // Non-wetting phase label for each index
DoubleArray Rho_n; // density field
DoubleArray Rho_w; // density field
DoubleArray Phi; // phase indicator field
@ -105,7 +105,9 @@ public:
SubPhase(std::shared_ptr<Domain> Dm);
~SubPhase();
void SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha, double beta);
void SetParams(double rhoA, double rhoB, double tauA, double tauB,
double force_x, double force_y, double force_z, double alpha,
double beta);
void Basic();
void Full();
void Write(int time);
@ -117,4 +119,3 @@ private:
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// Header file for two-phase averaging class
#ifndef TwoPhase_INC
#define TwoPhase_INC
@ -17,11 +33,11 @@
#include "IO/Reader.h"
#include "IO/Writer.h"
class TwoPhase {
//...........................................................................
int n_nw_pts,n_ns_pts,n_ws_pts,n_nws_pts,n_local_sol_pts,n_local_nws_pts;
int n_nw_pts, n_ns_pts, n_ws_pts, n_nws_pts, n_local_sol_pts,
n_local_nws_pts;
int n_nw_tris, n_ns_tris, n_ws_tris, n_nws_seg, n_local_sol_tris;
//...........................................................................
int nc;
@ -81,7 +97,8 @@ public:
double pan, paw; // local phase averaged pressure
// Global averages (all processes)
double pan_global, paw_global; // local phase averaged pressure
double vol_w_global, vol_n_global; // volumes the exclude the interfacial region
double vol_w_global,
vol_n_global; // volumes the exclude the interfacial region
double awn_global, ans_global, aws_global;
double lwns_global;
double efawns, efawns_global; // averaged contact angle
@ -127,7 +144,8 @@ public:
IntArray PhaseID; // Phase ID array (solid=0, non-wetting=1, wetting=2)
BlobIDArray Label_WP; // Wetting phase label
BlobIDArray Label_NWP; // Non-wetting phase label index (0:nblobs-1)
std::vector<BlobIDType> Label_NWP_map; // Non-wetting phase label for each index
std::vector<BlobIDType>
Label_NWP_map; // Non-wetting phase label for each index
DoubleArray SDn;
DoubleArray SDs;
DoubleArray Phase;
@ -163,7 +181,8 @@ public:
void UpdateMeshValues();
void UpdateSolid();
void ComputeDelPhi();
void ColorToSignedDistance(double Beta, DoubleArray &ColorData, DoubleArray &DistData);
void ColorToSignedDistance(double Beta, DoubleArray &ColorData,
DoubleArray &DistData);
void ComputeLocal();
void AssignComponentLabels();
void ComponentAverages();
@ -173,15 +192,11 @@ public:
int GetCubeLabel(int i, int j, int k, IntArray &BlobLabel);
void SortBlobs();
void PrintComponents(int timestep);
void SetParams(double rhoA, double rhoB, double tauA, double tauB, double force_x, double force_y, double force_z, double alpha);
double Volume_w(){
return wp_volume_global;
}
double Volume_n(){
return nwp_volume_global;
}
void SetParams(double rhoA, double rhoB, double tauA, double tauB,
double force_x, double force_y, double force_z,
double alpha);
double Volume_w() { return wp_volume_global; }
double Volume_n() { return nwp_volume_global; }
};
#endif

View File

@ -1,21 +1,38 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analysis/analysis.h"
#include "ProfilerApp.h"
#include <algorithm>
#include <iostream>
template<class TYPE>
inline TYPE* getPtr( std::vector<TYPE>& x ) { return x.empty() ? NULL:&x[0]; }
template<class TYPE>
inline const TYPE* getPtr( const std::vector<TYPE>& x ) { return x.empty() ? NULL:&x[0]; }
template <class TYPE> inline TYPE *getPtr(std::vector<TYPE> &x) {
return x.empty() ? NULL : &x[0];
}
template <class TYPE> inline const TYPE *getPtr(const std::vector<TYPE> &x) {
return x.empty() ? NULL : &x[0];
}
/******************************************************************
* Compute the blobs *
******************************************************************/
int ComputeBlob( const Array<bool>& isPhase, BlobIDArray& LocalBlobID, bool periodic, int start_id )
{
int ComputeBlob(const Array<bool> &isPhase, BlobIDArray &LocalBlobID,
bool periodic, int start_id) {
PROFILE_START("ComputeBlob", 1);
ASSERT(isPhase.size() == LocalBlobID.size());
const int Nx = isPhase.size(0); // maxima for the meshes
@ -26,27 +43,33 @@ int ComputeBlob( const Array<bool>& isPhase, BlobIDArray& LocalBlobID, bool peri
// Get the list of neighbors we need to check
int N_neighbors = 0;
int d[26][3];
bool include_corners = false; // Do we need to include cells that only touch at a corder/edge
bool include_corners =
false; // Do we need to include cells that only touch at a corder/edge
if (include_corners) {
// Include corners/edges as neighbors, check all cells
N_neighbors = 26;
const int tmp[26][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1},
{1,1,0},{1,-1,0},{-1,1,0},{-1,-1,0},{1,0,1},{-1,0,1},
{1,0,-1},{-1,0,-1},{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1},
{1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},{-1,1,1},{-1,1,-1},
{-1,-1,1},{-1,-1,-1}}; // directions to neighbors
const int tmp[26][3] = {
{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1},
{0, 0, -1}, {1, 1, 0}, {1, -1, 0}, {-1, 1, 0}, {-1, -1, 0},
{1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, {0, 1, 1},
{0, -1, 1}, {0, 1, -1}, {0, -1, -1}, {1, 1, 1}, {1, 1, -1},
{1, -1, 1}, {1, -1, -1}, {-1, 1, 1}, {-1, 1, -1}, {-1, -1, 1},
{-1, -1, -1}}; // directions to neighbors
memcpy(d, tmp, sizeof(tmp));
} else {
// Do not include corners/edges as neighbors
if (periodic) {
// Include all neighbors for periodic problems
N_neighbors = 6;
const int tmp[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}}; // directions to neighbors
const int tmp[6][3] = {
{1, 0, 0}, {-1, 0, 0}, {0, 1, 0},
{0, -1, 0}, {0, 0, 1}, {0, 0, -1}}; // directions to neighbors
memcpy(d, tmp, sizeof(tmp));
} else {
// We only need to include the lower neighbors for non-periodic problems
N_neighbors = 3;
const int tmp[3][3] = {{-1,0,0},{0,-1,0},{0,0,-1}}; // directions to neighbors
const int tmp[3][3] = {
{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}; // directions to neighbors
memcpy(d, tmp, sizeof(tmp));
}
}
@ -77,7 +100,8 @@ int ComputeBlob( const Array<bool>& isPhase, BlobIDArray& LocalBlobID, bool peri
z2 = z2 < 0 ? Nz - 1 : z2; // Periodic BC for x
z2 = z2 > Nz - 1 ? 0 : z2;
} else {
if ( x2<0 || x2>=Nx || y2<0 || y2>=Ny || z2<0 || z2>=Nz )
if (x2 < 0 || x2 >= Nx || y2 < 0 || y2 >= Ny ||
z2 < 0 || z2 >= Nz)
continue;
}
// Check if a neighbor has a known blob id
@ -103,7 +127,8 @@ int ComputeBlob( const Array<bool>& isPhase, BlobIDArray& LocalBlobID, bool peri
id = std::min(id, neighbor_ids[i]);
LocalBlobIDPtr[index] = id;
for (int i = 0; i < N_list; i++)
map[neighbor_ids[i]-start_id] = std::min(map[neighbor_ids[i]-start_id],id);
map[neighbor_ids[i] - start_id] =
std::min(map[neighbor_ids[i] - start_id], id);
}
}
}
@ -128,13 +153,12 @@ int ComputeBlob( const Array<bool>& isPhase, BlobIDArray& LocalBlobID, bool peri
return last - start_id + 1;
}
/******************************************************************
* Compute the local blob ids *
******************************************************************/
int ComputeLocalBlobIDs(const DoubleArray &Phase, const DoubleArray &SignDist,
double vF, double vS, BlobIDArray& LocalBlobID, bool periodic )
{
double vF, double vS, BlobIDArray &LocalBlobID,
bool periodic) {
PROFILE_START("ComputeLocalBlobIDs");
ASSERT(SignDist.size() == Phase.size());
size_t Nx = Phase.size(0);
@ -160,8 +184,8 @@ int ComputeLocalBlobIDs( const DoubleArray& Phase, const DoubleArray& SignDist,
PROFILE_STOP("ComputeLocalBlobIDs");
return nblobs;
}
int ComputeLocalPhaseComponent(const IntArray &PhaseID, int &VALUE, BlobIDArray &ComponentLabel, bool periodic )
{
int ComputeLocalPhaseComponent(const IntArray &PhaseID, int &VALUE,
BlobIDArray &ComponentLabel, bool periodic) {
PROFILE_START("ComputeLocalPhaseComponent");
size_t Nx = PhaseID.size(0);
size_t Ny = PhaseID.size(1);
@ -184,12 +208,11 @@ int ComputeLocalPhaseComponent(const IntArray &PhaseID, int &VALUE, BlobIDArray
return ncomponents;
}
/******************************************************************
* Reorder the global blob ids *
******************************************************************/
static int ReorderBlobIDs2( BlobIDArray& ID, int N_blobs, int ngx, int ngy, int ngz, const Utilities::MPI& comm )
{
static int ReorderBlobIDs2(BlobIDArray &ID, int N_blobs, int ngx, int ngy,
int ngz, const Utilities::MPI &comm) {
if (N_blobs == 0)
return 0;
PROFILE_START("ReorderBlobIDs2", 1);
@ -235,8 +258,7 @@ static int ReorderBlobIDs2( BlobIDArray& ID, int N_blobs, int ngx, int ngy, int
PROFILE_STOP("ReorderBlobIDs2", 1);
return N_blobs2;
}
void ReorderBlobIDs( BlobIDArray& ID, const Utilities::MPI& comm )
{
void ReorderBlobIDs(BlobIDArray &ID, const Utilities::MPI &comm) {
PROFILE_START("ReorderBlobIDs");
int tmp = ID.max() + 1;
int N_blobs = 0;
@ -245,7 +267,6 @@ void ReorderBlobIDs( BlobIDArray& ID, const Utilities::MPI& comm )
PROFILE_STOP("ReorderBlobIDs");
}
/******************************************************************
* Compute the global blob ids *
******************************************************************/
@ -254,14 +275,12 @@ struct global_id_info_struct {
std::set<int64_t> remote_ids;
};
// Send the local ids and their new value to all neighbors
static void updateRemoteIds(
const std::map<int64_t,global_id_info_struct>& map,
const std::vector<int>& neighbors,
int N_send, const std::vector<int>& N_recv,
int64_t *send_buf, std::vector<int64_t*>& recv_buf,
static void updateRemoteIds(const std::map<int64_t, global_id_info_struct> &map,
const std::vector<int> &neighbors, int N_send,
const std::vector<int> &N_recv, int64_t *send_buf,
std::vector<int64_t *> &recv_buf,
std::map<int64_t, int64_t> &remote_map,
const Utilities::MPI& comm )
{
const Utilities::MPI &comm) {
std::vector<MPI_Request> send_req(neighbors.size());
std::vector<MPI_Request> recv_req(neighbors.size());
auto it = map.begin();
@ -286,14 +305,14 @@ static void updateRemoteIds(
}
// Compute a new local id for each local id
static bool updateLocalIds(const std::map<int64_t, int64_t> &remote_map,
std::map<int64_t,global_id_info_struct>& map )
{
std::map<int64_t, global_id_info_struct> &map) {
bool changed = false;
std::map<int64_t, global_id_info_struct>::iterator it;
for (it = map.begin(); it != map.end(); ++it) {
int64_t id = it->second.new_id;
std::set<int64_t>::const_iterator it2;
for (it2=it->second.remote_ids.begin(); it2!=it->second.remote_ids.end(); ++it2) {
for (it2 = it->second.remote_ids.begin();
it2 != it->second.remote_ids.end(); ++it2) {
int64_t id2 = remote_map.find(*it2)->second;
id = std::min(id, id2);
}
@ -302,9 +321,9 @@ static bool updateLocalIds( const std::map<int64_t,int64_t>& remote_map,
}
return changed;
}
static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_info,
int nblobs, BlobIDArray& IDs, const Utilities::MPI& comm )
{
static int LocalToGlobalIDs(int nx, int ny, int nz,
const RankInfoStruct &rank_info, int nblobs,
BlobIDArray &IDs, const Utilities::MPI &comm) {
PROFILE_START("LocalToGlobalIDs", 1);
const int rank = rank_info.rank[1][1][1];
int nprocs = comm.getSize();
@ -330,7 +349,8 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
}
const BlobIDArray LocalIDs = IDs;
// Copy the ids and get the neighbors through the halos
fillHalo<BlobIDType> fillData(comm,rank_info,{nx,ny,nz},{1,1,1},0,1,{true,true,true});
fillHalo<BlobIDType> fillData(comm, rank_info, {nx, ny, nz}, {1, 1, 1}, 0,
1, {true, true, true});
fillData.fill(IDs);
// Create a list of all neighbor ranks (excluding self)
std::vector<int> neighbors;
@ -341,7 +361,8 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
neighbors.push_back(rank_info.rank[1][1][0]);
neighbors.push_back(rank_info.rank[1][1][2]);
std::sort(neighbors.begin(), neighbors.end());
neighbors.erase( std::unique( neighbors.begin(), neighbors.end() ), neighbors.end() );
neighbors.erase(std::unique(neighbors.begin(), neighbors.end()),
neighbors.end());
// Create a map of all local ids to the neighbor ids
std::map<int64_t, global_id_info_struct> map;
std::set<int64_t> local;
@ -378,7 +399,8 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
for (it = map.begin(); it != map.end(); ++it) {
int64_t id = it->first;
std::set<int64_t>::const_iterator it2;
for (it2=it->second.remote_ids.begin(); it2!=it->second.remote_ids.end(); ++it2) {
for (it2 = it->second.remote_ids.begin();
it2 != it->second.remote_ids.end(); ++it2) {
int64_t id2 = *it2;
id = std::min(id, id2);
remote_map.insert(std::pair<int64_t, int64_t>(id2, id2));
@ -391,7 +413,8 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
while (1) {
iteration++;
// Send the local ids and their new value to all neighbors
updateRemoteIds( map, neighbors, N_send, N_recv,send_buf, recv_buf, remote_map, comm );
updateRemoteIds(map, neighbors, N_send, N_recv, send_buf, recv_buf,
remote_map, comm);
// Compute a new local id for each local id
bool changed = updateLocalIds(remote_map, map);
// Check if we are finished
@ -405,7 +428,8 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
std::vector<int> final_map(nblobs, -1);
for (it = map.begin(); it != map.end(); ++it)
final_map[it->first - offset] = it->second.new_id;
for (std::set<int64_t>::const_iterator it2=local.begin(); it2!=local.end(); ++it2)
for (std::set<int64_t>::const_iterator it2 = local.begin();
it2 != local.end(); ++it2)
final_map[*it2 - offset] = *it2;
for (size_t i = 0; i < final_map.size(); i++)
ASSERT(final_map[i] >= 0);
@ -419,7 +443,8 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
}
}
// Fill the ghosts
fillHalo<BlobIDType> fillData2(comm,rank_info,{nx,ny,nz},{1,1,1},0,1,{true,true,true});
fillHalo<BlobIDType> fillData2(comm, rank_info, {nx, ny, nz}, {1, 1, 1}, 0,
1, {true, true, true});
fillData2.fill(IDs);
// Reorder based on size (and compress the id space
int N_blobs_global = ReorderBlobIDs2(IDs, N_blobs_tot, ngx, ngy, ngz, comm);
@ -430,38 +455,43 @@ static int LocalToGlobalIDs( int nx, int ny, int nz, const RankInfoStruct& rank_
PROFILE_STOP("LocalToGlobalIDs", 1);
return N_blobs_global;
}
int ComputeGlobalBlobIDs( int nx, int ny, int nz, const RankInfoStruct& rank_info,
const DoubleArray& Phase, const DoubleArray& SignDist, double vF, double vS,
BlobIDArray& GlobalBlobID, const Utilities::MPI& comm )
{
int ComputeGlobalBlobIDs(int nx, int ny, int nz,
const RankInfoStruct &rank_info,
const DoubleArray &Phase, const DoubleArray &SignDist,
double vF, double vS, BlobIDArray &GlobalBlobID,
const Utilities::MPI &comm) {
PROFILE_START("ComputeGlobalBlobIDs");
// First compute the local ids
int nblobs = ComputeLocalBlobIDs(Phase,SignDist,vF,vS,GlobalBlobID,false);
int nblobs =
ComputeLocalBlobIDs(Phase, SignDist, vF, vS, GlobalBlobID, false);
// Compute the global ids
int nglobal = LocalToGlobalIDs( nx, ny, nz, rank_info, nblobs, GlobalBlobID, comm );
int nglobal =
LocalToGlobalIDs(nx, ny, nz, rank_info, nblobs, GlobalBlobID, comm);
PROFILE_STOP("ComputeGlobalBlobIDs");
return nglobal;
}
int ComputeGlobalPhaseComponent( int nx, int ny, int nz, const RankInfoStruct& rank_info,
const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, const Utilities::MPI& comm )
{
int ComputeGlobalPhaseComponent(int nx, int ny, int nz,
const RankInfoStruct &rank_info,
const IntArray &PhaseID, int &VALUE,
BlobIDArray &GlobalBlobID,
const Utilities::MPI &comm) {
PROFILE_START("ComputeGlobalPhaseComponent");
// First compute the local ids
int nblobs = ComputeLocalPhaseComponent(PhaseID,VALUE,GlobalBlobID,false);
int nblobs =
ComputeLocalPhaseComponent(PhaseID, VALUE, GlobalBlobID, false);
// Compute the global ids
int nglobal = LocalToGlobalIDs( nx, ny, nz, rank_info, nblobs, GlobalBlobID, comm );
int nglobal =
LocalToGlobalIDs(nx, ny, nz, rank_info, nblobs, GlobalBlobID, comm);
PROFILE_STOP("ComputeGlobalPhaseComponent");
return nglobal;
}
/******************************************************************
* Compute the mapping of blob ids between timesteps *
******************************************************************/
typedef std::map<BlobIDType, std::map<BlobIDType, int64_t>> map_type;
template <class TYPE>
void gatherSet( std::set<TYPE>& set, const Utilities::MPI& comm )
{
void gatherSet(std::set<TYPE> &set, const Utilities::MPI &comm) {
int nprocs = comm.getSize();
std::vector<TYPE> send_data(set.begin(), set.end());
int send_count = send_data.size();
@ -475,8 +505,7 @@ void gatherSet( std::set<TYPE>& set, const Utilities::MPI& comm )
for (size_t i = 0; i < recv_data.size(); i++)
set.insert(recv_data[i]);
}
void gatherSrcIDMap( map_type& src_map, const Utilities::MPI& comm )
{
void gatherSrcIDMap(map_type &src_map, const Utilities::MPI &comm) {
int nprocs = comm.getSize();
std::vector<int64_t> send_data;
for (auto it = src_map.begin(); it != src_map.end(); ++it) {
@ -495,9 +524,10 @@ void gatherSrcIDMap( map_type& src_map, const Utilities::MPI& comm )
comm.allGather(send_count, getPtr(recv_count));
for (int i = 1; i < nprocs; i++)
recv_disp[i] = recv_disp[i - 1] + recv_count[i - 1];
std::vector<int64_t> recv_data(recv_disp[nprocs-1]+recv_count[nprocs-1]);
comm.allGather(getPtr(send_data),send_count,
getPtr(recv_data),getPtr(recv_count),getPtr(recv_disp),true);
std::vector<int64_t> recv_data(recv_disp[nprocs - 1] +
recv_count[nprocs - 1]);
comm.allGather(getPtr(send_data), send_count, getPtr(recv_data),
getPtr(recv_count), getPtr(recv_disp), true);
size_t i = 0;
src_map.clear();
while (i < recv_data.size()) {
@ -508,25 +538,25 @@ void gatherSrcIDMap( map_type& src_map, const Utilities::MPI& comm )
for (size_t j = 0; j < count; j++, i += 2) {
auto it = src_ids.find(recv_data[i]);
if (it == src_ids.end())
src_ids.insert(std::pair<BlobIDType,int64_t>(recv_data[i],recv_data[i+1]));
src_ids.insert(std::pair<BlobIDType, int64_t>(
recv_data[i], recv_data[i + 1]));
else
it->second += recv_data[i + 1];
}
}
}
void addSrcDstIDs(BlobIDType src_id, map_type &src_map, map_type &dst_map,
std::set<BlobIDType>& src, std::set<BlobIDType>& dst )
{
std::set<BlobIDType> &src, std::set<BlobIDType> &dst) {
src.insert(src_id);
const std::map<BlobIDType, int64_t> &dst_ids = dst_map[src_id];
for (std::map<BlobIDType,int64_t>::const_iterator it=dst_ids.begin(); it!=dst_ids.end(); ++it) {
for (std::map<BlobIDType, int64_t>::const_iterator it = dst_ids.begin();
it != dst_ids.end(); ++it) {
if (dst.find(it->first) == dst.end())
addSrcDstIDs(it->first, dst_map, src_map, dst, src);
}
}
ID_map_struct computeIDMap( int nx, int ny, int nz,
const BlobIDArray& ID1, const BlobIDArray& ID2, const Utilities::MPI& comm )
{
ID_map_struct computeIDMap(int nx, int ny, int nz, const BlobIDArray &ID1,
const BlobIDArray &ID2, const Utilities::MPI &comm) {
ASSERT(ID1.size() == ID2.size());
PROFILE_START("computeIDMap");
const int ngx = (ID1.size(0) - nx) / 2;
@ -547,7 +577,8 @@ ID_map_struct computeIDMap( int nx, int ny, int nz,
dst_set.insert(id2);
if (id1 >= 0 && id2 >= 0) {
std::map<BlobIDType, int64_t> &src_ids = src_map[id2];
std::map<BlobIDType,int64_t>::iterator it = src_ids.find(id1);
std::map<BlobIDType, int64_t>::iterator it =
src_ids.find(id1);
if (it == src_ids.end()) {
src_ids.insert(std::pair<BlobIDType, int64_t>(id1, 0));
it = src_ids.find(id1);
@ -563,10 +594,13 @@ ID_map_struct computeIDMap( int nx, int ny, int nz,
gatherSrcIDMap(src_map, comm);
// Compute the dst id map
map_type dst_map; // Map of the dst ids for each src id
for (map_type::const_iterator it=src_map.begin(); it!=src_map.end(); ++it) {
for (map_type::const_iterator it = src_map.begin(); it != src_map.end();
++it) {
BlobIDType id = it->first;
const std::map<BlobIDType, int64_t> &src_ids = it->second;
for (std::map<BlobIDType,int64_t>::const_iterator it2=src_ids.begin(); it2!=src_ids.end(); ++it2) {
for (std::map<BlobIDType, int64_t>::const_iterator it2 =
src_ids.begin();
it2 != src_ids.end(); ++it2) {
std::map<BlobIDType, int64_t> &dst_ids = dst_map[it2->first];
dst_ids.insert(std::pair<BlobIDType, int64_t>(id, it2->second));
}
@ -575,19 +609,22 @@ ID_map_struct computeIDMap( int nx, int ny, int nz,
// Perform the mapping of ids
ID_map_struct id_map;
// Find new blobs
for (std::set<BlobIDType>::const_iterator it=dst_set.begin(); it!=dst_set.end(); ++it) {
for (std::set<BlobIDType>::const_iterator it = dst_set.begin();
it != dst_set.end(); ++it) {
if (src_map.find(*it) == src_map.end())
id_map.created.push_back(*it);
}
// Fine blobs that disappeared
for (std::set<BlobIDType>::const_iterator it=src_set.begin(); it!=src_set.end(); ++it) {
for (std::set<BlobIDType>::const_iterator it = src_set.begin();
it != src_set.end(); ++it) {
if (dst_map.find(*it) == dst_map.end())
id_map.destroyed.push_back(*it);
}
// Find blobs with a 1-to-1 mapping
std::vector<BlobIDType> dst_list;
dst_list.reserve(src_map.size());
for (map_type::const_iterator it=src_map.begin(); it!=src_map.end(); ++it)
for (map_type::const_iterator it = src_map.begin(); it != src_map.end();
++it)
dst_list.push_back(it->first);
for (size_t i = 0; i < dst_list.size(); i++) {
int dst_id = dst_list[i];
@ -599,7 +636,8 @@ ID_map_struct computeIDMap( int nx, int ny, int nz,
ASSERT(dst_ids.begin()->first == dst_id);
src_map.erase(dst_id);
dst_map.erase(src_id);
id_map.src_dst.push_back(std::pair<BlobIDType,BlobIDType>(src_id,dst_id));
id_map.src_dst.push_back(
std::pair<BlobIDType, BlobIDType>(src_id, dst_id));
}
}
}
@ -610,30 +648,41 @@ ID_map_struct computeIDMap( int nx, int ny, int nz,
addSrcDstIDs(dst_map.begin()->first, src_map, dst_map, src, dst);
if (src.size() == 1) {
// Bubble split
id_map.split.push_back( BlobIDSplitStruct(*src.begin(),std::vector<BlobIDType>(dst.begin(),dst.end())) );
id_map.split.push_back(BlobIDSplitStruct(
*src.begin(), std::vector<BlobIDType>(dst.begin(), dst.end())));
} else if (dst.size() == 1) {
// Bubble merge
id_map.merge.push_back( BlobIDMergeStruct(std::vector<BlobIDType>(src.begin(),src.end()),*dst.begin()) );
id_map.merge.push_back(BlobIDMergeStruct(
std::vector<BlobIDType>(src.begin(), src.end()), *dst.begin()));
} else {
// Bubble split/merge
id_map.merge_split.push_back(BlobIDMergeSplitStruct(
std::vector<BlobIDType>(src.begin(),src.end()), std::vector<BlobIDType>(dst.begin(),dst.end() ) ) );
std::vector<BlobIDType>(src.begin(), src.end()),
std::vector<BlobIDType>(dst.begin(), dst.end())));
}
// Add the overlaps
for (std::set<BlobIDType>::const_iterator it1=src.begin(); it1!=src.end(); ++it1) {
for (std::set<BlobIDType>::const_iterator it1 = src.begin();
it1 != src.end(); ++it1) {
const std::map<BlobIDType, int64_t> &dst_ids = dst_map[*it1];
for (std::set<BlobIDType>::const_iterator it2=dst.begin(); it2!=dst.end(); ++it2) {
for (std::set<BlobIDType>::const_iterator it2 = dst.begin();
it2 != dst.end(); ++it2) {
std::pair<BlobIDType, BlobIDType> id(*it1, *it2);
int64_t overlap = 0;
const std::map<BlobIDType,int64_t>::const_iterator it = dst_ids.find(*it2);
if ( it != dst_ids.end() ) { overlap = it->second; }
id_map.overlap.insert(std::pair<OverlapID,int64_t>(id,overlap));
const std::map<BlobIDType, int64_t>::const_iterator it =
dst_ids.find(*it2);
if (it != dst_ids.end()) {
overlap = it->second;
}
id_map.overlap.insert(
std::pair<OverlapID, int64_t>(id, overlap));
}
}
// Clear the mapped entries
for (std::set<BlobIDType>::const_iterator it=src.begin(); it!=src.end(); ++it)
for (std::set<BlobIDType>::const_iterator it = src.begin();
it != src.end(); ++it)
dst_map.erase(*it);
for (std::set<BlobIDType>::const_iterator it=dst.begin(); it!=dst.end(); ++it)
for (std::set<BlobIDType>::const_iterator it = dst.begin();
it != dst.end(); ++it)
src_map.erase(*it);
}
ASSERT(src_map.empty());
@ -642,14 +691,14 @@ ID_map_struct computeIDMap( int nx, int ny, int nz,
return id_map;
}
/******************************************************************
* Renumber the ids *
******************************************************************/
typedef std::vector<BlobIDType> IDvec;
inline void renumber( const std::vector<BlobIDType>& id1, const std::vector<BlobIDType>& id2,
const std::map<OverlapID,int64_t>& overlap, std::vector<BlobIDType>& new_ids, BlobIDType& id_max )
{
inline void renumber(const std::vector<BlobIDType> &id1,
const std::vector<BlobIDType> &id2,
const std::map<OverlapID, int64_t> &overlap,
std::vector<BlobIDType> &new_ids, BlobIDType &id_max) {
if (id2.empty()) {
// No dst ids to set
} else if (id1.empty()) {
@ -671,7 +720,10 @@ inline void renumber( const std::vector<BlobIDType>& id1, const std::vector<Blob
Array<int64_t> cost(id1.size(), id2.size());
for (size_t j = 0; j < id2.size(); j++) {
for (size_t i = 0; i < id1.size(); i++) {
cost(i,j) = overlap.find(std::pair<BlobIDType,BlobIDType>(id1[i],id2[j]))->second;
cost(i, j) =
overlap
.find(std::pair<BlobIDType, BlobIDType>(id1[i], id2[j]))
->second;
}
}
// While we have not mapped all dst ids
@ -708,31 +760,37 @@ inline void renumber( const std::vector<BlobIDType>& id1, const std::vector<Blob
}
}
}
inline void renumberIDs( const std::vector<BlobIDType>& new_ids, BlobIDType& id )
{
inline void renumberIDs(const std::vector<BlobIDType> &new_ids,
BlobIDType &id) {
id = new_ids[id];
}
inline void renumberIDs( const std::vector<BlobIDType>& new_ids, std::vector<BlobIDType>& ids )
{
inline void renumberIDs(const std::vector<BlobIDType> &new_ids,
std::vector<BlobIDType> &ids) {
for (size_t i = 0; i < ids.size(); i++)
ids[i] = new_ids[ids[i]];
}
void getNewIDs( ID_map_struct& map, BlobIDType& id_max, std::vector<BlobIDType>& new_ids )
{
void getNewIDs(ID_map_struct &map, BlobIDType &id_max,
std::vector<BlobIDType> &new_ids) {
new_ids.resize(0);
// Get the new id numbers for each map type
for (size_t i = 0; i < map.src_dst.size(); i++)
renumber(IDvec(1,map.src_dst[i].first),IDvec(1,map.src_dst[i].second),map.overlap,new_ids,id_max);
renumber(IDvec(1, map.src_dst[i].first),
IDvec(1, map.src_dst[i].second), map.overlap, new_ids, id_max);
for (size_t i = 0; i < map.created.size(); i++)
renumber(std::vector<BlobIDType>(),IDvec(1,map.created[i]),map.overlap,new_ids,id_max);
renumber(std::vector<BlobIDType>(), IDvec(1, map.created[i]),
map.overlap, new_ids, id_max);
for (size_t i = 0; i < map.destroyed.size(); i++)
renumber(IDvec(1,map.destroyed[i]),std::vector<BlobIDType>(),map.overlap,new_ids,id_max);
renumber(IDvec(1, map.destroyed[i]), std::vector<BlobIDType>(),
map.overlap, new_ids, id_max);
for (size_t i = 0; i < map.split.size(); i++)
renumber(IDvec(1,map.split[i].first),map.split[i].second,map.overlap,new_ids,id_max);
renumber(IDvec(1, map.split[i].first), map.split[i].second, map.overlap,
new_ids, id_max);
for (size_t i = 0; i < map.merge.size(); i++)
renumber(map.merge[i].first,IDvec(1,map.merge[i].second),map.overlap,new_ids,id_max);
renumber(map.merge[i].first, IDvec(1, map.merge[i].second), map.overlap,
new_ids, id_max);
for (size_t i = 0; i < map.merge_split.size(); i++)
renumber(map.merge_split[i].first,map.merge_split[i].second,map.overlap,new_ids,id_max);
renumber(map.merge_split[i].first, map.merge_split[i].second,
map.overlap, new_ids, id_max);
// Renumber the ids in the map
for (size_t i = 0; i < map.src_dst.size(); i++)
renumberIDs(new_ids, map.src_dst[i].second);
@ -744,14 +802,14 @@ void getNewIDs( ID_map_struct& map, BlobIDType& id_max, std::vector<BlobIDType>&
for (size_t i = 0; i < map.merge_split.size(); i++)
renumberIDs(new_ids, map.merge_split[i].second);
std::map<OverlapID, int64_t> overlap2;
for (std::map<OverlapID,int64_t>::const_iterator it=map.overlap.begin(); it!=map.overlap.begin(); ++it) {
for (std::map<OverlapID, int64_t>::const_iterator it = map.overlap.begin();
it != map.overlap.begin(); ++it) {
OverlapID id = it->first;
renumberIDs(new_ids, id.second);
overlap2.insert(std::pair<OverlapID, int64_t>(id, it->second));
}
}
void renumberIDs( const std::vector<BlobIDType>& new_ids, BlobIDArray& IDs )
{
void renumberIDs(const std::vector<BlobIDType> &new_ids, BlobIDArray &IDs) {
size_t N = IDs.length();
BlobIDType *ids = IDs.data();
for (size_t i = 0; i < N; i++) {
@ -761,17 +819,17 @@ void renumberIDs( const std::vector<BlobIDType>& new_ids, BlobIDArray& IDs )
}
}
/******************************************************************
* Write the id map for the given timestep *
******************************************************************/
void writeIDMap( const ID_map_struct& map, long long int timestep, const std::string& filename )
{
void writeIDMap(const ID_map_struct &map, long long int timestep,
const std::string &filename) {
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank();
if (rank != 0)
return;
bool empty = map.created.empty() && map.destroyed.empty() &&
map.split.empty() && map.merge.empty() && map.merge_split.empty();
map.split.empty() && map.merge.empty() &&
map.merge_split.empty();
for (size_t i = 0; i < map.src_dst.size(); i++)
empty = empty && map.src_dst[i].first == map.src_dst[i].second;
if (timestep != 0 && empty)
@ -793,30 +851,38 @@ void writeIDMap( const ID_map_struct& map, long long int timestep, const std::st
fprintf(fid, " %lli-", static_cast<long long int>(map.destroyed[i]));
for (size_t i = 0; i < map.src_dst.size(); i++) {
if (map.src_dst[i].first != map.src_dst[i].second)
fprintf(fid," %lli-%lli",static_cast<long long int>(map.src_dst[i].first),
fprintf(fid, " %lli-%lli",
static_cast<long long int>(map.src_dst[i].first),
static_cast<long long int>(map.src_dst[i].second));
}
for (size_t i = 0; i < map.split.size(); i++) {
fprintf(fid," %lli-%lli",static_cast<long long int>(map.split[i].first),
fprintf(fid, " %lli-%lli",
static_cast<long long int>(map.split[i].first),
static_cast<long long int>(map.split[i].second[0]));
for (size_t j = 1; j < map.split[i].second.size(); j++)
fprintf(fid,"/%lli",static_cast<long long int>(map.split[i].second[j]));
fprintf(fid, "/%lli",
static_cast<long long int>(map.split[i].second[j]));
}
for (size_t i = 0; i < map.merge.size(); i++) {
fprintf(fid," %lli",static_cast<long long int>(map.merge[i].first[0]));
fprintf(fid, " %lli",
static_cast<long long int>(map.merge[i].first[0]));
for (size_t j = 1; j < map.merge[i].first.size(); j++)
fprintf(fid,"/%lli",static_cast<long long int>(map.merge[i].first[j]));
fprintf(fid, "/%lli",
static_cast<long long int>(map.merge[i].first[j]));
fprintf(fid, "-%lli", static_cast<long long int>(map.merge[i].second));
}
for (size_t i = 0; i < map.merge_split.size(); i++) {
fprintf(fid," %lli",static_cast<long long int>(map.merge_split[i].first[0]));
fprintf(fid, " %lli",
static_cast<long long int>(map.merge_split[i].first[0]));
for (size_t j = 1; j < map.merge_split[i].first.size(); j++)
fprintf(fid,"/%lli",static_cast<long long int>(map.merge_split[i].first[j]));
fprintf(fid,"-%lli",static_cast<long long int>(map.merge_split[i].second[0]));
fprintf(fid, "/%lli",
static_cast<long long int>(map.merge_split[i].first[j]));
fprintf(fid, "-%lli",
static_cast<long long int>(map.merge_split[i].second[0]));
for (size_t j = 1; j < map.merge_split[i].second.size(); j++)
fprintf(fid,"/%lli",static_cast<long long int>(map.merge_split[i].second[j]));
fprintf(fid, "/%lli",
static_cast<long long int>(map.merge_split[i].second[j]));
}
fprintf(fid, "\n");
fclose(fid);
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Analysis_H_INC
#define Analysis_H_INC
@ -8,12 +24,10 @@
#include <map>
#include <vector>
// Define types to use for blob ids
typedef int32_t BlobIDType;
typedef Array<BlobIDType> BlobIDArray;
/*!
* @brief Compute the blob
* @details Compute the blob (F>vf|S>vs) starting from (i,j,k) - oil blob
@ -27,7 +41,8 @@ typedef Array<BlobIDType> BlobIDArray;
* @return Returns the number of blobs
*/
int ComputeLocalBlobIDs(const DoubleArray &Phase, const DoubleArray &SignDist,
double vF, double vS, BlobIDArray& LocalBlobID, bool periodic=true );
double vF, double vS, BlobIDArray &LocalBlobID,
bool periodic = true);
/*!
* @brief Compute blob of an arbitrary phase
@ -38,8 +53,8 @@ int ComputeLocalBlobIDs( const DoubleArray& Phase, const DoubleArray& SignDist,
* @param[out] ComponentLabel
* @param[in] periodic
*/
int ComputeLocalPhaseComponent( const IntArray &PhaseID, int &VALUE, IntArray &ComponentLabel, bool periodic );
int ComputeLocalPhaseComponent(const IntArray &PhaseID, int &VALUE,
IntArray &ComponentLabel, bool periodic);
/*!
* @brief Compute the blob
@ -57,10 +72,11 @@ int ComputeLocalPhaseComponent( const IntArray &PhaseID, int &VALUE, IntArray &C
* @param[in] comm MPI communicator
* @return Returns the number of blobs
*/
int ComputeGlobalBlobIDs( int nx, int ny, int nz, const RankInfoStruct& rank_info,
const DoubleArray& Phase, const DoubleArray& SignDist, double vF, double vS,
BlobIDArray& GlobalBlobID, const Utilities::MPI& comm );
int ComputeGlobalBlobIDs(int nx, int ny, int nz,
const RankInfoStruct &rank_info,
const DoubleArray &Phase, const DoubleArray &SignDist,
double vF, double vS, BlobIDArray &GlobalBlobID,
const Utilities::MPI &comm);
/*!
* @brief Compute component of the specified phase
@ -76,9 +92,11 @@ int ComputeGlobalBlobIDs( int nx, int ny, int nz, const RankInfoStruct& rank_inf
* @param[in] comm The communicator to use
* @return Return the number of components in the specified phase
*/
int ComputeGlobalPhaseComponent( int nx, int ny, int nz, const RankInfoStruct& rank_info,
const IntArray &PhaseID, int &VALUE, BlobIDArray &GlobalBlobID, const Utilities::MPI& comm );
int ComputeGlobalPhaseComponent(int nx, int ny, int nz,
const RankInfoStruct &rank_info,
const IntArray &PhaseID, int &VALUE,
BlobIDArray &GlobalBlobID,
const Utilities::MPI &comm);
/*!
* @brief Reorder the blobs
@ -89,29 +107,33 @@ int ComputeGlobalPhaseComponent( int nx, int ny, int nz, const RankInfoStruct& r
*/
void ReorderBlobIDs(BlobIDArray &ID, const Utilities::MPI &comm);
typedef std::pair<BlobIDType, std::vector<BlobIDType>> BlobIDSplitStruct;
typedef std::pair<std::vector<BlobIDType>, BlobIDType> BlobIDMergeStruct;
typedef std::pair<std::vector<BlobIDType>,std::vector<BlobIDType> > BlobIDMergeSplitStruct;
typedef std::pair<std::vector<BlobIDType>, std::vector<BlobIDType>>
BlobIDMergeSplitStruct;
typedef std::pair<BlobIDType, BlobIDType> OverlapID;
struct ID_map_struct {
std::vector<BlobIDType> created; // list of new blobs that were created
std::vector<BlobIDType> destroyed; // list of blobs that disappeared
std::vector<std::pair<BlobIDType,BlobIDType> > src_dst; // one-one mapping of blobs (first,second timestep id)
std::vector<std::pair<BlobIDType, BlobIDType>>
src_dst; // one-one mapping of blobs (first,second timestep id)
std::vector<BlobIDSplitStruct> split; // list of blobs that split
std::vector<BlobIDMergeStruct> merge; // list of blobs that merged
std::vector<BlobIDMergeSplitStruct> merge_split; // list of blobs that both merged and split
std::map<OverlapID,int64_t> overlap; // for ids that are not a 1-1 mapping, this is a list of the overlaps <src,dst>
std::vector<BlobIDMergeSplitStruct>
merge_split; // list of blobs that both merged and split
std::map<OverlapID, int64_t>
overlap; // for ids that are not a 1-1 mapping, this is a list of the overlaps <src,dst>
//! Empty constructor
ID_map_struct() {}
//! Create initial map from N blobs (ordered 1:N-1)
ID_map_struct(int N) {
created.resize(N);
for (int i=0; i<N; i++) { created[i]=i; }
for (int i = 0; i < N; i++) {
created[i] = i;
}
}
};
/*!
* @brief Get the mapping of blob ids between iterations
* @details This functions computes the map of blob ids between iterations
@ -124,8 +146,8 @@ struct ID_map_struct {
* @param[in] ID2 The blob ids at the second timestep
* @param[in] comm The communicator to use
*/
ID_map_struct computeIDMap( int nx, int ny, int nz, const BlobIDArray& ID1, const BlobIDArray& ID2, const Utilities::MPI& comm );
ID_map_struct computeIDMap(int nx, int ny, int nz, const BlobIDArray &ID1,
const BlobIDArray &ID2, const Utilities::MPI &comm);
/*!
* @brief Compute the new global ids based on the map
@ -135,8 +157,8 @@ ID_map_struct computeIDMap( int nx, int ny, int nz, const BlobIDArray& ID1, cons
* @param[in] id_max The globally largest id used previously
* @param[out] new_ids The newly renumbered blob ids (0:ids.max())
*/
void getNewIDs( ID_map_struct& map, BlobIDType& id_max, std::vector<BlobIDType>& new_ids );
void getNewIDs(ID_map_struct &map, BlobIDType &id_max,
std::vector<BlobIDType> &new_ids);
/*!
* @brief Update the blob ids based on mapping
@ -147,7 +169,6 @@ void getNewIDs( ID_map_struct& map, BlobIDType& id_max, std::vector<BlobIDType>&
*/
void renumberIDs(const std::vector<BlobIDType> &new_ids, BlobIDArray &IDs);
/*!
* @brief Write the ID map
* @details This functions writes the id map fo an iteration.
@ -157,8 +178,7 @@ void renumberIDs( const std::vector<BlobIDType>& new_ids, BlobIDArray& IDs );
* @param[in] timestep The current timestep (timestep 0 creates the file)
* @param[in] filename The filename to write/append
*/
void writeIDMap( const ID_map_struct& map, long long int timestep, const std::string& filename );
void writeIDMap(const ID_map_struct &map, long long int timestep,
const std::string &filename);
#endif

View File

@ -1,17 +1,13 @@
#include "analysis/dcel.h"
DCEL::DCEL(){
}
DCEL::DCEL() {}
DCEL::~DCEL() {
TriangleCount = 0;
VertexCount = 0;
}
int DCEL::Face(int index){
return FaceData[index];
}
int DCEL::Face(int index) { return FaceData[index]; }
void DCEL::Write() {
int e1, e2, e3;
@ -32,7 +28,8 @@ void DCEL::Write(){
fclose(TRIANGLES);
}
void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, const int j, const int k){
void DCEL::LocalIsosurface(const DoubleArray &A, double value, const int i,
const int j, const int k) {
Point P, Q;
Point PlaceHolder;
Point C0, C1, C2, C3, C4, C5, C6, C7;
@ -48,14 +45,30 @@ void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
double CubeValues[8];
// Points corresponding to cube corners
C0.x = 0.0; C0.y = 0.0; C0.z = 0.0;
C1.x = 1.0; C1.y = 0.0; C1.z = 0.0;
C2.x = 1.0; C2.y = 1.0; C2.z = 0.0;
C3.x = 0.0; C3.y = 1.0; C3.z = 0.0;
C4.x = 0.0; C4.y = 0.0; C4.z = 1.0;
C5.x = 1.0; C5.y = 0.0; C5.z = 1.0;
C6.x = 1.0; C6.y = 1.0; C6.z = 1.0;
C7.x = 0.0; C7.y = 1.0; C7.z = 1.0;
C0.x = 0.0;
C0.y = 0.0;
C0.z = 0.0;
C1.x = 1.0;
C1.y = 0.0;
C1.z = 0.0;
C2.x = 1.0;
C2.y = 1.0;
C2.z = 0.0;
C3.x = 0.0;
C3.y = 1.0;
C3.z = 0.0;
C4.x = 0.0;
C4.y = 0.0;
C4.z = 1.0;
C5.x = 1.0;
C5.y = 0.0;
C5.z = 1.0;
C6.x = 1.0;
C6.y = 1.0;
C6.z = 1.0;
C7.x = 0.0;
C7.y = 1.0;
C7.z = 1.0;
CubeValues[0] = A(i, j, k) - value;
CubeValues[1] = A(i + 1, j, k) - value;
@ -70,14 +83,22 @@ void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
//Determine the index into the edge table which
//tells us which vertices are inside of the surface
int CubeIndex = 0;
if (CubeValues[0] < 0.0f) CubeIndex |= 1;
if (CubeValues[1] < 0.0f) CubeIndex |= 2;
if (CubeValues[2] < 0.0f) CubeIndex |= 4;
if (CubeValues[3] < 0.0f) CubeIndex |= 8;
if (CubeValues[4] < 0.0f) CubeIndex |= 16;
if (CubeValues[5] < 0.0f) CubeIndex |= 32;
if (CubeValues[6] < 0.0f) CubeIndex |= 64;
if (CubeValues[7] < 0.0f) CubeIndex |= 128;
if (CubeValues[0] < 0.0f)
CubeIndex |= 1;
if (CubeValues[1] < 0.0f)
CubeIndex |= 2;
if (CubeValues[2] < 0.0f)
CubeIndex |= 4;
if (CubeValues[3] < 0.0f)
CubeIndex |= 8;
if (CubeValues[4] < 0.0f)
CubeIndex |= 16;
if (CubeValues[5] < 0.0f)
CubeIndex |= 32;
if (CubeValues[6] < 0.0f)
CubeIndex |= 64;
if (CubeValues[7] < 0.0f)
CubeIndex |= 128;
//Find the vertices where the surface intersects the cube
if (edgeTable[CubeIndex] & 1) {
@ -145,10 +166,8 @@ void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
for (int idx = 0; idx < 12; idx++)
LocalRemap[idx] = -1;
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx++)
{
if(LocalRemap[triTable[CubeIndex][idx]] == -1)
{
for (int idx = 0; triTable[CubeIndex][idx] != -1; idx++) {
if (LocalRemap[triTable[CubeIndex][idx]] == -1) {
NewVertexList[VertexCount] = VertexList[triTable[CubeIndex][idx]];
LocalRemap[triTable[CubeIndex][idx]] = VertexCount;
VertexCount++;
@ -219,24 +238,33 @@ void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
int V2 = halfedge.data(1, idx);
// Find all the twins within the cube
for (int jdx = 0; jdx < EdgeCount; jdx++) {
if (halfedge.data(1,jdx) == V1 && halfedge.data(0,jdx) == V2){
if (halfedge.data(1, jdx) == V1 &&
halfedge.data(0, jdx) == V2) {
// this is the pair
halfedge.data(3, idx) = jdx;
halfedge.data(3, jdx) = idx;
}
if (halfedge.data(1,jdx) == V2 && halfedge.data(0,jdx) == V1 && !(idx==jdx)){
std::printf("WARNING: half edges with identical orientation! \n");
if (halfedge.data(1, jdx) == V2 &&
halfedge.data(0, jdx) == V1 && !(idx == jdx)) {
std::printf(
"WARNING: half edges with identical orientation! \n");
}
}
// Use "ghost" twins if edge is on a cube face
P = cellvertices[V1];
Q = cellvertices[V2];
if (P.x == 0.0 && Q.x == 0.0) halfedge.data(3,idx) = -1; // ghost twin for x=0 face
if (P.x == 1.0 && Q.x == 1.0) halfedge.data(3,idx) = -4; // ghost twin for x=1 face
if (P.y == 0.0 && Q.y == 0.0) halfedge.data(3,idx) = -2; // ghost twin for y=0 face
if (P.y == 1.0 && Q.y == 1.0) halfedge.data(3,idx) = -5; // ghost twin for y=1 face
if (P.z == 0.0 && Q.z == 0.0) halfedge.data(3,idx) = -3; // ghost twin for z=0 face
if (P.z == 1.0 && Q.z == 1.0) halfedge.data(3,idx) = -6; // ghost twin for z=1 face
if (P.x == 0.0 && Q.x == 0.0)
halfedge.data(3, idx) = -1; // ghost twin for x=0 face
if (P.x == 1.0 && Q.x == 1.0)
halfedge.data(3, idx) = -4; // ghost twin for x=1 face
if (P.y == 0.0 && Q.y == 0.0)
halfedge.data(3, idx) = -2; // ghost twin for y=0 face
if (P.y == 1.0 && Q.y == 1.0)
halfedge.data(3, idx) = -5; // ghost twin for y=1 face
if (P.z == 0.0 && Q.z == 0.0)
halfedge.data(3, idx) = -3; // ghost twin for z=0 face
if (P.z == 1.0 && Q.z == 1.0)
halfedge.data(3, idx) = -6; // ghost twin for z=1 face
}
}
@ -250,31 +278,36 @@ void DCEL::LocalIsosurface(const DoubleArray& A, double value, const int i, cons
}
}
Point DCEL::TriNormal(int edge)
{
Point DCEL::TriNormal(int edge) {
Point P, Q, R;
Point U, V, W;
double nx, ny, nz, len;
// at cube faces define outward normal to cube
if (edge == -1) {
W.x = -1.0; W.y = 0.0; W.z = 0.0; // x cube face
}
else if (edge == -2){
W.x = 0.0; W.y = -1.0; W.z = 0.0; // y cube face
}
else if (edge == -3){
W.x = 0.0; W.y = 0.0; W.z = -1.0; // z cube face
}
else if (edge == -4){
W.x = 1.0; W.y = 0.0; W.z = 0.0; // x cube face
}
else if (edge == -5){
W.x = 0.0; W.y = 1.0; W.z = 0.0; // y cube face
}
else if (edge == -6){
W.x = 0.0; W.y = 0.0; W.z = 1.0; // z cube face
}
else{
W.x = -1.0;
W.y = 0.0;
W.z = 0.0; // x cube face
} else if (edge == -2) {
W.x = 0.0;
W.y = -1.0;
W.z = 0.0; // y cube face
} else if (edge == -3) {
W.x = 0.0;
W.y = 0.0;
W.z = -1.0; // z cube face
} else if (edge == -4) {
W.x = 1.0;
W.y = 0.0;
W.z = 0.0; // x cube face
} else if (edge == -5) {
W.x = 0.0;
W.y = 1.0;
W.z = 0.0; // y cube face
} else if (edge == -6) {
W.x = 0.0;
W.y = 0.0;
W.z = 1.0; // z cube face
} else {
// vertices for triange
int e2 = halfedge.next(edge);
int e3 = halfedge.next(e2);
@ -289,13 +322,14 @@ Point DCEL::TriNormal(int edge)
ny = U.z * V.x - U.x * V.z;
nz = U.x * V.y - U.y * V.x;
len = sqrt(nx * nx + ny * ny + nz * nz);
W.x = nx/len; W.y = ny/len; W.z = nz/len;
W.x = nx / len;
W.y = ny / len;
W.z = nz / len;
}
return W;
}
double DCEL::EdgeAngle(int edge)
{
double DCEL::EdgeAngle(int edge) {
double angle;
double dotprod;
Point P, Q, R; // triangle vertices
@ -320,16 +354,22 @@ double DCEL::EdgeAngle(int edge)
double nz = W.x * V.y - W.y * V.x;
length = sqrt(nx * nx + ny * ny + nz * nz);
// new value for V is this normal vector
V.x = nx/length; V.y = ny/length; V.z = nz/length;
V.x = nx / length;
V.y = ny / length;
V.z = nz / length;
dotprod = U.x * V.x + U.y * V.y + U.z * V.z;
if (dotprod < 0.f) {
//printf("negative dot product on face\n");
dotprod = -dotprod;
V.x = -V.x; V.y = -V.y; V.z = -V.z;
V.x = -V.x;
V.y = -V.y;
V.z = -V.z;
}
if (dotprod > 1.f) dotprod=1.f;
if (dotprod < -1.f) dotprod=-1.f;
if (dotprod > 1.f)
dotprod = 1.f;
if (dotprod < -1.f)
dotprod = -1.f;
angle = acos(dotprod);
/* project onto plane of cube face also works
W = U - dotprod*V;
@ -339,11 +379,12 @@ double DCEL::EdgeAngle(int edge)
if (dotprod < -1.f) dotprod=-1.f;
angle = acos(dotprod);
*/
}
else{
} else {
dotprod = U.x * V.x + U.y * V.y + U.z * V.z;
if (dotprod > 1.f) dotprod=1.f;
if (dotprod < -1.f) dotprod=-1.f;
if (dotprod > 1.f)
dotprod = 1.f;
if (dotprod < -1.f)
dotprod = -1.f;
angle = 0.5 * acos(dotprod);
}
// determine if angle is concave or convex based on edge normal
@ -362,13 +403,13 @@ double DCEL::EdgeAngle(int edge)
// concave
angle = -angle;
}
if (angle != angle) angle = 0.0;
if (angle != angle)
angle = 0.0;
//printf("angle=%f,dot=%f (Edge=%i, twin=%i): P={%f, %f, %f}, Q={%f, %f, %f} U={%f, %f, %f}, V={%f, %f, %f}\n",angle,dotprod,edge,halfedge.twin(edge),P.x,P.y,P.z,Q.x,Q.y,Q.z,U.x,U.y,U.z,V.x,V.y,V.z);
return angle;
}
void iso_surface(const Array<double>&Field, const double isovalue)
{
void iso_surface(const Array<double> &Field, const double isovalue) {
DCEL object;
int e1, e2, e3;
FILE *TRIANGLES;
@ -392,14 +433,17 @@ void iso_surface(const Array<double>&Field, const double isovalue)
// P1.x += 1.0*i; P1.y += 1.0*j; P1.z +=1.0*k;
//P2.x += 1.0*i; P2.y += 1.0*j; P2.z +=1.0*k;
//P3.x += 1.0*i; P3.y += 1.0*j; P3.z +=1.0*k;
fprintf(TRIANGLES,"facet normal %f %f %f\n",Normal.x,Normal.y,Normal.z);
fprintf(TRIANGLES, "facet normal %f %f %f\n", Normal.x,
Normal.y, Normal.z);
fprintf(TRIANGLES, " outer loop\n");
fprintf(TRIANGLES," vertex %f %f %f\n",P1.x,P1.y,P1.z);
fprintf(TRIANGLES," vertex %f %f %f\n",P2.x,P2.y,P2.z);
fprintf(TRIANGLES," vertex %f %f %f\n",P3.x,P3.y,P3.z);
fprintf(TRIANGLES, " vertex %f %f %f\n", P1.x, P1.y,
P1.z);
fprintf(TRIANGLES, " vertex %f %f %f\n", P2.x, P2.y,
P2.z);
fprintf(TRIANGLES, " vertex %f %f %f\n", P3.x, P3.y,
P3.z);
fprintf(TRIANGLES, " endloop\n");
fprintf(TRIANGLES, "endfacet\n");
}
}
}

View File

@ -34,7 +34,6 @@ private:
std::vector<Point> d_data;
};
/**
* \class Halfedge
* @brief store half edge for DCEL data structure
@ -75,7 +74,8 @@ public:
int face();
Vertex vertex;
Halfedge halfedge;
void LocalIsosurface(const DoubleArray& A, double value, int i, int j, int k);
void LocalIsosurface(const DoubleArray &A, double value, int i, int j,
int k);
void Write();
int Face(int index);

View File

@ -1,17 +1,32 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analysis/distance.h"
/******************************************************************
* A fast distance calculation *
******************************************************************/
template <class TYPE>
void CalcDist(Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
const std::array<bool,3>& periodic, const std::array<double,3>& dx )
{
const std::array<bool, 3> &periodic,
const std::array<double, 3> &dx) {
ASSERT(Distance.size() == ID.size());
std::array<int, 3> n = {Dm.Nx - 2, Dm.Ny - 2, Dm.Nz - 2};
fillHalo<int> fillData( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,false,false}, periodic );
fillHalo<int> fillData(Dm.Comm, Dm.rank_info, n, {1, 1, 1}, 50, 1,
{true, false, false}, periodic);
Array<int> id(ID.size());
Array<Vec> vecDist(Distance.size());
for (size_t i = 0; i < ID.length(); i++)
@ -22,13 +37,12 @@ void CalcDist( Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
Distance(i) = id(i) * vecDist(i).norm();
}
/******************************************************************
* Vector-based distance calculation *
* Initialize cells adjacent to boundaries *
******************************************************************/
static void calcVecInitialize( Array<Vec> &d, const Array<int> &ID, double dx, double dy, double dz )
{
static void calcVecInitialize(Array<Vec> &d, const Array<int> &ID, double dx,
double dy, double dz) {
d.fill(Vec(1e50, 1e50, 1e50));
const double dx0 = 0.5 * dx;
const double dy0 = 0.5 * dy;
@ -47,12 +61,18 @@ static void calcVecInitialize( Array<Vec> &d, const Array<int> &ID, double dx, d
bool x[2] = {id != ID(i - 1, j, k), id != ID(i + 1, j, k)};
bool y[2] = {id != ID(i, j - 1, k), id != ID(i, j + 1, k)};
bool z[2] = {id != ID(i, j, k - 1), id != ID(i, j, k + 1)};
if ( x[0] ) d(i,j,k) = Vec( dx0, 0, 0 );
if ( x[1] ) d(i,j,k) = Vec( -dx0, 0, 0 );
if ( y[0] ) d(i,j,k) = Vec( 0, dy0, 0 );
if ( y[1] ) d(i,j,k) = Vec( 0, -dy0, 0 );
if ( z[0] ) d(i,j,k) = Vec( 0, 0, dz0 );
if ( z[1] ) d(i,j,k) = Vec( 0, 0, -dz0 );
if (x[0])
d(i, j, k) = Vec(dx0, 0, 0);
if (x[1])
d(i, j, k) = Vec(-dx0, 0, 0);
if (y[0])
d(i, j, k) = Vec(0, dy0, 0);
if (y[1])
d(i, j, k) = Vec(0, -dy0, 0);
if (z[0])
d(i, j, k) = Vec(0, 0, dz0);
if (z[1])
d(i, j, k) = Vec(0, 0, -dz0);
/*if ( x[0] && y[0] ) d(i,j,k) = Vec( dxy0, dxy0, 0 );
if ( x[0] && y[1] ) d(i,j,k) = Vec( dxy0, -dxy0, 0 );
if ( x[1] && y[0] ) d(i,j,k) = Vec( -dxy0, dxy0, 0 );
@ -68,16 +88,14 @@ static void calcVecInitialize( Array<Vec> &d, const Array<int> &ID, double dx, d
}
}
}
}
/******************************************************************
* Vector-based distance calculation *
* Update interior cells *
******************************************************************/
static double calcVecUpdateInterior( Array<Vec> &d, double dx, double dy, double dz )
{
static double calcVecUpdateInterior(Array<Vec> &d, double dx, double dy,
double dz) {
double err = 0;
int Nx = d.size(0);
int Ny = d.size(1);
@ -125,18 +143,18 @@ static double calcVecUpdateInterior( Array<Vec> &d, double dx, double dy, double
return err;
}
/******************************************************************
* Vector-based distance calculation *
******************************************************************/
void CalcVecDist(Array<Vec> &d, const Array<int> &ID0, const Domain &Dm,
const std::array<bool,3>& periodic, const std::array<double,3>& dx )
{
const std::array<bool, 3> &periodic,
const std::array<double, 3> &dx) {
std::array<int, 3> N = {Dm.Nx, Dm.Ny, Dm.Nz};
std::array<int, 3> n = {Dm.Nx - 2, Dm.Ny - 2, Dm.Nz - 2};
// Create ID with ghosts
Array<int> ID(N[0], N[1], N[2]);
fillHalo<int> fillDataID( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,true,true}, periodic );
fillHalo<int> fillDataID(Dm.Comm, Dm.rank_info, n, {1, 1, 1}, 50, 1,
{true, true, true}, periodic);
fillDataID.copy(ID0, ID);
// Fill ghosts with nearest neighbor
for (int k = 1; k < N[2] - 1; k++) {
@ -160,7 +178,8 @@ void CalcVecDist( Array<Vec> &d, const Array<int> &ID0, const Domain &Dm,
// Communicate ghosts
fillDataID.fill(ID);
// Create communicator for distance
fillHalo<Vec> fillData( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,false,false}, periodic );
fillHalo<Vec> fillData(Dm.Comm, Dm.rank_info, n, {1, 1, 1}, 50, 1,
{true, false, false}, periodic);
// Calculate the local distances
calcVecInitialize(d, ID, dx[0], dx[1], dx[2]);
double err = 1e100;
@ -182,9 +201,10 @@ void CalcVecDist( Array<Vec> &d, const Array<int> &ID0, const Domain &Dm,
}
}
// Explicit instantiations
template void CalcDist<float>( Array<float>&, const Array<char>&, const Domain&, const std::array<bool,3>&, const std::array<double,3>& );
template void CalcDist<double>( Array<double>&, const Array<char>&, const Domain&, const std::array<bool,3>&, const std::array<double,3>& );
template void CalcDist<float>(Array<float> &, const Array<char> &,
const Domain &, const std::array<bool, 3> &,
const std::array<double, 3> &);
template void CalcDist<double>(Array<double> &, const Array<char> &,
const Domain &, const std::array<bool, 3> &,
const std::array<double, 3> &);

View File

@ -1,10 +1,25 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Distance_H_INC
#define Distance_H_INC
#include "common/Domain.h"
#include "common/Array.hpp"
struct Vec {
double x;
double y;
@ -14,8 +29,10 @@ struct Vec {
inline double norm() const { return sqrt(x * x + y * y + z * z); }
inline double norm2() const { return x * x + y * y + z * z; }
};
inline bool operator<(const Vec& l, const Vec& r){ return l.x*l.x+l.y*l.y+l.z*l.z < r.x*r.x+r.y*r.y+r.z*r.z; }
inline bool operator<(const Vec &l, const Vec &r) {
return l.x * l.x + l.y * l.y + l.z * l.z <
r.x * r.x + r.y * r.y + r.z * r.z;
}
/*!
* @brief Calculate the distance using a simple method
@ -28,7 +45,8 @@ inline bool operator<(const Vec& l, const Vec& r){ return l.x*l.x+l.y*l.y+l.z*l.
*/
template <class TYPE>
void CalcDist(Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
const std::array<bool,3>& periodic = {true,true,true}, const std::array<double,3>& dx = {1,1,1} );
const std::array<bool, 3> &periodic = {true, true, true},
const std::array<double, 3> &dx = {1, 1, 1});
/*!
* @brief Calculate the distance using a simple method
@ -40,6 +58,7 @@ void CalcDist( Array<TYPE> &Distance, const Array<char> &ID, const Domain &Dm,
* @param[in] dx Cell size
*/
void CalcVecDist(Array<Vec> &Distance, const Array<int> &ID, const Domain &Dm,
const std::array<bool,3>& periodic = {true,true,true}, const std::array<double,3>& dx = {1,1,1} );
const std::array<bool, 3> &periodic = {true, true, true},
const std::array<double, 3> &dx = {1, 1, 1});
#endif

View File

@ -1,9 +1,24 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analysis/filters.h"
#include "math.h"
#include "ProfilerApp.h"
void Mean3D( const Array<double> &Input, Array<double> &Output )
{
void Mean3D(const Array<double> &Input, Array<double> &Output) {
PROFILE_START("Mean3D");
// Perform a 3D Mean filter on Input array
int i, j, k;
@ -17,12 +32,21 @@ void Mean3D( const Array<double> &Input, Array<double> &Output )
for (i = 1; i < Nx - 1; i++) {
double MeanValue = Input(i, j, k);
// next neighbors
MeanValue += Input(i+1,j,k)+Input(i,j+1,k)+Input(i,j,k+1)+Input(i-1,j,k)+Input(i,j-1,k)+Input(i,j,k-1);
MeanValue += Input(i+1,j+1,k)+Input(i-1,j+1,k)+Input(i+1,j-1,k)+Input(i-1,j-1,k);
MeanValue += Input(i+1,j,k+1)+Input(i-1,j,k+1)+Input(i+1,j,k-1)+Input(i-1,j,k-1);
MeanValue += Input(i,j+1,k+1)+Input(i,j-1,k+1)+Input(i,j+1,k-1)+Input(i,j-1,k-1);
MeanValue += Input(i+1,j+1,k+1)+Input(i-1,j+1,k+1)+Input(i+1,j-1,k+1)+Input(i-1,j-1,k+1);
MeanValue += Input(i+1,j+1,k-1)+Input(i-1,j+1,k-1)+Input(i+1,j-1,k-1)+Input(i-1,j-1,k-1);
MeanValue += Input(i + 1, j, k) + Input(i, j + 1, k) +
Input(i, j, k + 1) + Input(i - 1, j, k) +
Input(i, j - 1, k) + Input(i, j, k - 1);
MeanValue += Input(i + 1, j + 1, k) + Input(i - 1, j + 1, k) +
Input(i + 1, j - 1, k) + Input(i - 1, j - 1, k);
MeanValue += Input(i + 1, j, k + 1) + Input(i - 1, j, k + 1) +
Input(i + 1, j, k - 1) + Input(i - 1, j, k - 1);
MeanValue += Input(i, j + 1, k + 1) + Input(i, j - 1, k + 1) +
Input(i, j + 1, k - 1) + Input(i, j - 1, k - 1);
MeanValue +=
Input(i + 1, j + 1, k + 1) + Input(i - 1, j + 1, k + 1) +
Input(i + 1, j - 1, k + 1) + Input(i - 1, j - 1, k + 1);
MeanValue +=
Input(i + 1, j + 1, k - 1) + Input(i - 1, j + 1, k - 1) +
Input(i + 1, j - 1, k - 1) + Input(i - 1, j - 1, k - 1);
Output(i, j, k) = MeanValue / 27.0;
}
}
@ -30,8 +54,7 @@ void Mean3D( const Array<double> &Input, Array<double> &Output )
PROFILE_STOP("Mean3D");
}
void Med3D( const Array<float> &Input, Array<float> &Output )
{
void Med3D(const Array<float> &Input, Array<float> &Output) {
PROFILE_START("Med3D");
// Perform a 3D Median filter on Input array with specified width
int i, j, k, ii, jj, kk;
@ -83,10 +106,9 @@ void Med3D( const Array<float> &Input, Array<float> &Output )
PROFILE_STOP("Med3D");
}
int NLM3D(const Array<float> &Input, Array<float> &Mean,
const Array<float> &Distance, Array<float> &Output, const int d, const float h)
{
const Array<float> &Distance, Array<float> &Output, const int d,
const float h) {
PROFILE_START("NLM3D");
// Implemenation of 3D non-local means filter
// d determines the width of the search volume
@ -117,7 +139,8 @@ int NLM3D( const Array<float> &Input, Array<float> &Mean,
kmax = std::min(Nz - 1, k + d);
// Populate the list with values in the window
sum = 0; weight=0;
sum = 0;
weight = 0;
for (kk = kmin; kk < kmax; kk++) {
for (jj = jmin; jj < jmax; jj++) {
for (ii = imin; ii < imax; ii++) {
@ -137,10 +160,10 @@ int NLM3D( const Array<float> &Input, Array<float> &Mean,
for (j = 1; j < Ny - 1; j++) {
for (i = 1; i < Nx - 1; i++) {
if (fabs(Distance(i, j, k)) < THRESHOLD_DIST) {
// compute the expensive non-local means
sum = 0; weight=0;
sum = 0;
weight = 0;
imin = std::max(0, i - d);
jmin = std::max(0, j - d);
@ -162,8 +185,7 @@ int NLM3D( const Array<float> &Input, Array<float> &Mean,
returnCount++;
//Output(i,j,k) = Mean(i,j,k);
Output(i, j, k) = sum / weight;
}
else{
} else {
// Just return the mean
Output(i, j, k) = Mean(i, j, k);
}

View File

@ -1,7 +1,22 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Filters_H_INC
#define Filters_H_INC
#include "common/Array.h"
/*!
@ -31,7 +46,7 @@ void Med3D( const Array<float> &Input, Array<float> &Output );
* @param[in] h
*/
int NLM3D(const Array<float> &Input, Array<float> &Mean,
const Array<float> &Distance, Array<float> &Output, const int d, const float h);
const Array<float> &Distance, Array<float> &Output, const int d,
const float h);
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Generate a histogram for volumetric, interfacial and common curve properties
* copyright 2014, James E. McClure
@ -12,18 +28,19 @@ struct Histogram{
maximum = v2;
delta = (maximum - minimum) / HISTOGRAM_RESOLUTION;
}
~Histogram{
delete *data;
}
~Histogram { delete *data; }
double *data;
double minimum, maximum, delta;
// Adds value into the histogram
void IncludeValue(double value, double weight) {
idx = floor((value - min) / delta);
if (idx > HISTOGRAM_RESOLUTION) ;
else if (idx < 0) ;
else data[idx] += weight;
if (idx > HISTOGRAM_RESOLUTION)
;
else if (idx < 0)
;
else
data[idx] += weight;
}
// Returns the maximum value in the histogram
@ -38,7 +55,8 @@ struct Histogram{
// Resets the histogram to zero
void Reset() {
for (idx=0; idx<HISTOGRAM_RESOLUTION; idx++) data[idx] = 0.0;
for (idx = 0; idx < HISTOGRAM_RESOLUTION; idx++)
data[idx] = 0.0;
}
private:

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// These functions mimic the behavior of imfilter in MATLAB
#ifndef included_imfilter
#define included_imfilter
@ -6,14 +22,11 @@
#include "common/Array.h"
#include <vector>
namespace imfilter {
//! enum to store the BC type
enum class BC { fixed = 0, symmetric = 1, replicate = 2, circular = 3 };
/*!
* @brief N-D filtering of multidimensional images
* @details imfilter filters the multidimensional array A with the
@ -32,8 +45,9 @@ enum class BC { fixed=0, symmetric=1, replicate=2, circular=3 };
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/
template <class TYPE>
Array<TYPE> imfilter( const Array<TYPE>& A, const Array<TYPE>& H, const std::vector<imfilter::BC>& boundary, const TYPE X=0 );
Array<TYPE> imfilter(const Array<TYPE> &A, const Array<TYPE> &H,
const std::vector<imfilter::BC> &boundary,
const TYPE X = 0);
/*!
* @brief N-D filtering of multidimensional images
@ -57,8 +71,8 @@ Array<TYPE> imfilter( const Array<TYPE>& A, const Array<TYPE>& H, const std::vec
template <class TYPE>
Array<TYPE> imfilter(const Array<TYPE> &A, const std::vector<int> &Nh,
std::function<TYPE(const Array<TYPE> &)> H,
const std::vector<imfilter::BC>& boundary, const TYPE X=0 );
const std::vector<imfilter::BC> &boundary,
const TYPE X = 0);
/*!
* @brief N-D filtering of multidimensional images
@ -79,10 +93,10 @@ Array<TYPE> imfilter( const Array<TYPE>& A, const std::vector<int>& Nh,
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/
template <class TYPE>
Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<Array<TYPE>>& H,
Array<TYPE>
imfilter_separable(const Array<TYPE> &A, const std::vector<Array<TYPE>> &H,
const std::vector<imfilter::BC> &boundary, const TYPE X = 0);
/*!
* @brief N-D filtering of multidimensional images
* @details imfilter filters the multidimensional array A with the
@ -102,11 +116,11 @@ Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<Array<TY
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/
template <class TYPE>
Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh,
Array<TYPE>
imfilter_separable(const Array<TYPE> &A, const std::vector<int> &Nh,
std::vector<std::function<TYPE(const Array<TYPE> &)>> H,
const std::vector<imfilter::BC> &boundary, const TYPE X = 0);
/*!
* @brief N-D filtering of multidimensional images
* @details imfilter filters the multidimensional array A with the
@ -127,11 +141,11 @@ Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh
* @param[in] X The value to use for boundary conditions (only used if boundary==fixed)
*/
template <class TYPE>
Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh,
Array<TYPE>
imfilter_separable(const Array<TYPE> &A, const std::vector<int> &Nh,
std::vector<std::function<TYPE(int, const TYPE *)>> H,
const std::vector<imfilter::BC> &boundary, const TYPE X = 0);
/**
* @brief Create a filter to use with imfilter
* @details This function creates one of several predefined filters
@ -148,13 +162,11 @@ Array<TYPE> imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh
* \param[in] args An optional argument that some of the filters use
*/
template <class TYPE>
Array<TYPE> create_filter( const std::vector<int>& N, const std::string &type, const void *args = NULL );
}
Array<TYPE> create_filter(const std::vector<int> &N, const std::string &type,
const void *args = NULL);
} // namespace imfilter
#include "analysis/imfilter.hpp"
#endif

View File

@ -1,17 +1,47 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analysis/imfilter.h"
#include "ProfilerApp.h"
#include <math.h>
#include <string.h>
#define IMFILTER_INSIST INSIST
#define IMFILTER_ASSERT ASSERT
#define IMFILTER_ERROR ERROR
// Function to convert an index
static inline int imfilter_index( int index, const int N, const imfilter::BC bc )
{
static inline int imfilter_index(int index, const int N,
const imfilter::BC bc) {
if (index < 0 || index >= N) {
if (bc == imfilter::BC::symmetric) {
index = (2 * N - index) % N;
@ -26,12 +56,11 @@ static inline int imfilter_index( int index, const int N, const imfilter::BC bc
return index;
}
// Function to copy a 1D array and pad with the appropriate BC
template <class TYPE>
static inline void copy_array(const int N, const int Ns, const int Nh,
const TYPE *A, const imfilter::BC BC, const TYPE X, TYPE *B )
{
const TYPE *A, const imfilter::BC BC,
const TYPE X, TYPE *B) {
// Fill the center with a memcpy
for (int i = 0; i < N; i++)
B[i + Nh] = A[i * Ns];
@ -44,14 +73,12 @@ static inline void copy_array( const int N, const int Ns, const int Nh,
}
}
/********************************************************
* Perform a 1D filter in a single direction *
********************************************************/
template <class TYPE>
static void filter_direction(int Ns, int N, int Ne, int Nh, const TYPE *H,
imfilter::BC boundary, TYPE X, TYPE *A )
{
imfilter::BC boundary, TYPE X, TYPE *A) {
if (Nh < 0)
IMFILTER_ERROR("Invalid filter size");
if (Nh == 0) {
@ -75,8 +102,8 @@ static void filter_direction( int Ns, int N, int Ne, int Nh, const TYPE *H,
}
template <class TYPE>
static void filter_direction(int Ns, int N, int Ne, int Nh,
std::function<TYPE(const Array<TYPE>&)> H, imfilter::BC boundary, TYPE X, TYPE *A )
{
std::function<TYPE(const Array<TYPE> &)> H,
imfilter::BC boundary, TYPE X, TYPE *A) {
if (Nh < 0)
IMFILTER_ERROR("Invalid filter size");
TYPE *tmp = new TYPE[N + 2 * Nh];
@ -95,8 +122,8 @@ static void filter_direction( int Ns, int N, int Ne, int Nh,
}
template <class TYPE>
static void filter_direction(int Ns, int N, int Ne, int Nh,
std::function<TYPE(int, const TYPE*)> H, imfilter::BC boundary, TYPE X, TYPE *A )
{
std::function<TYPE(int, const TYPE *)> H,
imfilter::BC boundary, TYPE X, TYPE *A) {
if (Nh < 0)
IMFILTER_ERROR("Invalid filter size");
TYPE *tmp = new TYPE[N + 2 * Nh];
@ -111,14 +138,12 @@ static void filter_direction( int Ns, int N, int Ne, int Nh,
delete[] tmp;
}
/********************************************************
* Create a filter *
********************************************************/
template <class TYPE>
Array<TYPE> imfilter::create_filter( const std::vector<int>& N0, const std::string &type, const void *args )
{
Array<TYPE> imfilter::create_filter(const std::vector<int> &N0,
const std::string &type, const void *args) {
std::vector<size_t> N2(N0.size());
for (size_t i = 0; i < N2.size(); i++)
N2[i] = 2 * N0[i] + 1;
@ -156,12 +181,10 @@ Array<TYPE> imfilter::create_filter( const std::vector<int>& N0, const std::stri
return h;
}
// Perform 2-D filtering
template <class TYPE>
void imfilter_2D(int Nx, int Ny, const TYPE *A, int Nhx, int Nhy, const TYPE *H,
imfilter::BC BCx, imfilter::BC BCy, const TYPE X, TYPE *B )
{
imfilter::BC BCx, imfilter::BC BCy, const TYPE X, TYPE *B) {
IMFILTER_ASSERT(A != B);
PROFILE_START("imfilter_2D");
memset(B, 0, Nx * Ny * sizeof(TYPE));
@ -193,13 +216,11 @@ void imfilter_2D( int Nx, int Ny, const TYPE *A, int Nhx, int Nhy, const TYPE *H
PROFILE_STOP("imfilter_2D");
}
// Perform 3-D filtering
template <class TYPE>
void imfilter_3D( int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy, int Nhz,
const TYPE *H, imfilter::BC BCx, imfilter::BC BCy, imfilter::BC BCz,
const TYPE X, TYPE *B )
{
void imfilter_3D(int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy,
int Nhz, const TYPE *H, imfilter::BC BCx, imfilter::BC BCy,
imfilter::BC BCz, const TYPE X, TYPE *B) {
IMFILTER_ASSERT(A != B);
PROFILE_START("imfilter_3D");
memset(B, 0, Nx * Ny * Nz * sizeof(TYPE));
@ -215,7 +236,8 @@ void imfilter_3D( int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy, int N
for (int ih = -Nhx; ih <= Nhx; ih++) {
int i2 = imfilter_index(i1 + ih, Nx, BCx);
bool fixed = i2 == -1 || j2 == -1 || k2 == -1;
TYPE A2 = fixed ? X : A[i2 + j2 * Nx + k2 * Nx * Ny];
TYPE A2 =
fixed ? X : A[i2 + j2 * Nx + k2 * Nx * Ny];
tmp += H[ijkh] * A2;
ijkh++;
}
@ -228,20 +250,20 @@ void imfilter_3D( int Nx, int Ny, int Nz, const TYPE *A, int Nhx, int Nhy, int N
PROFILE_STOP("imfilter_3D");
}
/********************************************************
* Perform N-D filtering *
********************************************************/
template <class TYPE>
Array<TYPE> imfilter::imfilter( const Array<TYPE>& A,
const Array<TYPE>& H, const std::vector<imfilter::BC>& BC, const TYPE X )
{
Array<TYPE> imfilter::imfilter(const Array<TYPE> &A, const Array<TYPE> &H,
const std::vector<imfilter::BC> &BC,
const TYPE X) {
IMFILTER_ASSERT(A.ndim() == H.ndim());
IMFILTER_ASSERT(A.ndim() == BC.size());
std::vector<size_t> Nh = H.size();
for (int d = 0; d < A.ndim(); d++) {
Nh[d] = (H.size(d) - 1) / 2;
IMFILTER_INSIST(2*Nh[d]+1==H.size(d),"Filter must be of size 2*N+1");
IMFILTER_INSIST(2 * Nh[d] + 1 == H.size(d),
"Filter must be of size 2*N+1");
}
auto B = A;
if (A.ndim() == 1) {
@ -249,20 +271,21 @@ Array<TYPE> imfilter::imfilter( const Array<TYPE>& A,
filter_direction(1, A.size(0), 1, Nh[0], H.data(), BC[0], X, B.data());
PROFILE_STOP("imfilter_1D");
} else if (A.ndim() == 2) {
imfilter_2D( A.size(0), A.size(1), A.data(), Nh[0], Nh[1], H.data(), BC[0], BC[1], X, B.data() );
imfilter_2D(A.size(0), A.size(1), A.data(), Nh[0], Nh[1], H.data(),
BC[0], BC[1], X, B.data());
} else if (A.ndim() == 3) {
imfilter_3D( A.size(0), A.size(1), A.size(2), A.data(),
Nh[0], Nh[1], Nh[2], H.data(), BC[0], BC[1], BC[2], X, B.data() );
imfilter_3D(A.size(0), A.size(1), A.size(2), A.data(), Nh[0], Nh[1],
Nh[2], H.data(), BC[0], BC[1], BC[2], X, B.data());
} else {
IMFILTER_ERROR("Arbitrary dimension not yet supported");
}
return B;
}
template <class TYPE>
Array<TYPE> imfilter::imfilter( const Array<TYPE>& A, const std::vector<int>& Nh0,
Array<TYPE>
imfilter::imfilter(const Array<TYPE> &A, const std::vector<int> &Nh0,
std::function<TYPE(const Array<TYPE> &)> H,
const std::vector<imfilter::BC>& BC0, const TYPE X )
{
const std::vector<imfilter::BC> &BC0, const TYPE X) {
PROFILE_START("imfilter (lambda)");
IMFILTER_ASSERT(A.ndim() == Nh0.size());
IMFILTER_ASSERT(A.ndim() == BC0.size());
@ -271,7 +294,8 @@ Array<TYPE> imfilter::imfilter( const Array<TYPE>& A, const std::vector<int>& Nh
Nh2[d] = 2 * Nh0[d] + 1;
auto B = A;
Array<TYPE> data(Nh2);
IMFILTER_INSIST(A.ndim()<=3,"Not programmed for more than 3 dimensions yet");
IMFILTER_INSIST(A.ndim() <= 3,
"Not programmed for more than 3 dimensions yet");
auto N = A.size();
auto Nh = Nh0;
auto BC = BC0;
@ -288,7 +312,8 @@ Array<TYPE> imfilter::imfilter( const Array<TYPE>& A, const std::vector<int>& Nh
for (int ih = -Nh[0]; ih <= Nh[0]; ih++) {
int i2 = imfilter_index(i1 + ih, N[0], BC[0]);
bool fixed = i2 == -1 || j2 == -1 || k2 == -1;
data(ih+Nh[0],jh+Nh[1],kh+Nh[2]) = fixed ? X : A(i2,j2,k2);
data(ih + Nh[0], jh + Nh[1], kh + Nh[2]) =
fixed ? X : A(i2, j2, k2);
}
}
}
@ -300,15 +325,13 @@ Array<TYPE> imfilter::imfilter( const Array<TYPE>& A, const std::vector<int>& Nh
return B;
}
/********************************************************
* imfilter with separable filter functions *
********************************************************/
template <class TYPE>
Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A,
const std::vector<Array<TYPE>>& H,
const std::vector<imfilter::BC>& boundary, const TYPE X )
{
Array<TYPE> imfilter::imfilter_separable(
const Array<TYPE> &A, const std::vector<Array<TYPE>> &H,
const std::vector<imfilter::BC> &boundary, const TYPE X) {
PROFILE_START("imfilter_separable");
IMFILTER_ASSERT(A.ndim() == (int)H.size());
IMFILTER_ASSERT(A.ndim() == (int)boundary.size());
@ -316,7 +339,8 @@ Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A,
for (int d = 0; d < A.ndim(); d++) {
IMFILTER_ASSERT(H[d].ndim() == 1);
Nh[d] = (H[d].length() - 1) / 2;
IMFILTER_INSIST(2*Nh[d]+1==H[d].length(),"Filter must be of size 2*N+1");
IMFILTER_INSIST(2 * Nh[d] + 1 == H[d].length(),
"Filter must be of size 2*N+1");
}
auto B = A;
for (int d = 0; d < A.ndim(); d++) {
@ -327,16 +351,17 @@ Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A,
Ns *= A.size(d2);
for (int d2 = d + 1; d2 < A.ndim(); d2++)
Ne *= A.size(d2);
filter_direction( Ns, N, Ne, Nh[d], H[d].data(), boundary[d], X, B.data() );
filter_direction(Ns, N, Ne, Nh[d], H[d].data(), boundary[d], X,
B.data());
}
PROFILE_STOP("imfilter_separable");
return B;
}
template <class TYPE>
Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh,
Array<TYPE> imfilter::imfilter_separable(
const Array<TYPE> &A, const std::vector<int> &Nh,
std::vector<std::function<TYPE(const Array<TYPE> &)>> H,
const std::vector<imfilter::BC>& boundary, const TYPE X )
{
const std::vector<imfilter::BC> &boundary, const TYPE X) {
PROFILE_START("imfilter_separable (lambda)");
IMFILTER_ASSERT(A.ndim() == (int)boundary.size());
auto B = A;
@ -354,10 +379,10 @@ Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, const std::vecto
return B;
}
template <class TYPE>
Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, const std::vector<int>& Nh,
Array<TYPE> imfilter::imfilter_separable(
const Array<TYPE> &A, const std::vector<int> &Nh,
std::vector<std::function<TYPE(int, const TYPE *)>> H,
const std::vector<imfilter::BC>& boundary, const TYPE X )
{
const std::vector<imfilter::BC> &boundary, const TYPE X) {
PROFILE_START("imfilter_separable (function)");
IMFILTER_ASSERT(A.ndim() == (int)boundary.size());
auto B = A;
@ -374,5 +399,3 @@ Array<TYPE> imfilter::imfilter_separable( const Array<TYPE>& A, const std::vecto
PROFILE_STOP("imfilter_separable (function)");
return B;
}

View File

@ -1,7 +1,8 @@
#include <analysis/morphology.h>
// Implementation of morphological opening routine
inline void PackID(const int *list, int count, signed char *sendbuf, signed char *ID){
inline void PackID(const int *list, int count, signed char *sendbuf,
signed char *ID) {
// Fill in the phase ID values from neighboring processors
// This packs up the values that need to be sent from one processor to another
int idx, n;
@ -13,7 +14,8 @@ inline void PackID(const int *list, int count, signed char *sendbuf, signed char
}
//***************************************************************************************
inline void UnpackID(const int *list, int count, signed char *recvbuf, signed char *ID){
inline void UnpackID(const int *list, int count, signed char *recvbuf,
signed char *ID) {
// Fill in the phase ID values from neighboring processors
// This unpacks the values once they have been recieved from neighbors
int idx, n;
@ -30,9 +32,7 @@ Morphology::Morphology(){
sendtag = recvtag = 1381;
}
Morphology::~Morphology(){
}
Morphology::~Morphology() {}
void Morphology::Initialize(std::shared_ptr<Domain> Dm, DoubleArray &Distance) {
/* Loop over all faces and determine overlaps */
@ -89,7 +89,8 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
morphRadius.resize(recvLoc);
//..............................
/* send the morphological radius */
Dm->Comm.Irecv(&morphRadius[recvOffset_X],recvCount,Dm->rank_X(),recvtag+0);
Dm->Comm.Irecv(&morphRadius[recvOffset_X], recvCount, Dm->rank_X(),
recvtag + 0);
Dm->Comm.send(&tmpDistance[0], sendCount, Dm->rank_x(), sendtag + 0);
/* send the shift values */
Dm->Comm.Irecv(&xShift[recvOffset_X], recvCount, Dm->rank_X(), recvtag + 1);
@ -136,7 +137,8 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
morphRadius.resize(recvLoc);
//..............................
/* send the morphological radius */
Dm->Comm.Irecv(&morphRadius[recvOffset_x],recvCount,Dm->rank_x(),recvtag+0);
Dm->Comm.Irecv(&morphRadius[recvOffset_x], recvCount, Dm->rank_x(),
recvtag + 0);
Dm->Comm.send(&tmpDistance[0], sendCount, Dm->rank_X(), sendtag + 0);
/* send the shift values */
Dm->Comm.Irecv(&xShift[recvOffset_x], recvCount, Dm->rank_x(), recvtag + 1);
@ -184,7 +186,8 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
morphRadius.resize(recvLoc);
//..............................
/* send the morphological radius */
Dm->Comm.Irecv(&morphRadius[recvOffset_Y],recvCount,Dm->rank_Y(),recvtag+0);
Dm->Comm.Irecv(&morphRadius[recvOffset_Y], recvCount, Dm->rank_Y(),
recvtag + 0);
Dm->Comm.send(&tmpDistance[0], sendCount, Dm->rank_y(), sendtag + 0);
/* send the shift values */
Dm->Comm.Irecv(&xShift[recvOffset_Y], recvCount, Dm->rank_Y(), recvtag + 1);
@ -231,7 +234,8 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
morphRadius.resize(recvLoc);
//..............................
/* send the morphological radius */
Dm->Comm.Irecv(&morphRadius[recvOffset_y],recvCount,Dm->rank_y(),recvtag+0);
Dm->Comm.Irecv(&morphRadius[recvOffset_y], recvCount, Dm->rank_y(),
recvtag + 0);
Dm->Comm.send(&tmpDistance[0], sendCount, Dm->rank_Y(), sendtag + 0);
/* send the shift values */
Dm->Comm.Irecv(&xShift[recvOffset_y], recvCount, Dm->rank_y(), recvtag + 1);
@ -279,7 +283,8 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
morphRadius.resize(recvLoc);
//..............................
/* send the morphological radius */
Dm->Comm.Irecv(&morphRadius[recvOffset_Z],recvCount,Dm->rank_Z(),recvtag+0);
Dm->Comm.Irecv(&morphRadius[recvOffset_Z], recvCount, Dm->rank_Z(),
recvtag + 0);
Dm->Comm.send(&tmpDistance[0], sendCount, Dm->rank_z(), sendtag + 0);
/* send the shift values */
Dm->Comm.Irecv(&xShift[recvOffset_Z], recvCount, Dm->rank_Z(), recvtag + 1);
@ -325,7 +330,8 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
morphRadius.resize(recvLoc);
//..............................
/* send the morphological radius */
Dm->Comm.Irecv(&morphRadius[recvOffset_z],recvCount,Dm->rank_z(),recvtag+0);
Dm->Comm.Irecv(&morphRadius[recvOffset_z], recvCount, Dm->rank_z(),
recvtag + 0);
Dm->Comm.send(&tmpDistance[0], sendCount, Dm->rank_Z(), sendtag + 0);
/* send the shift values */
Dm->Comm.Irecv(&xShift[recvOffset_z], recvCount, Dm->rank_z(), recvtag + 1);
@ -352,10 +358,11 @@ void Morphology::Initialize(std::shared_ptr <Domain> Dm, DoubleArray &Distance){
printf(" offset %i for send (z) %i \n", sendOffset_z, sendCount_z);
printf(" offset %i for send (Z) %i \n", sendOffset_Z, sendCount_Z);
*/
}
int Morphology::GetOverlaps(std::shared_ptr <Domain> Dm, signed char *id, const signed char ErodeLabel, const signed char NewLabel){
int Morphology::GetOverlaps(std::shared_ptr<Domain> Dm, signed char *id,
const signed char ErodeLabel,
const signed char NewLabel) {
int Nx = Dm->Nx;
int Ny = Dm->Ny;
@ -369,28 +376,40 @@ int Morphology::GetOverlaps(std::shared_ptr <Domain> Dm, signed char *id, const
localID[idx] = id[n];
}
//printf("send x -- offset: %i, count: %i \n",sendOffset_x,sendCount_x);
Dm->Comm.Irecv(&nonlocalID[recvOffset_X],recvCount_X,Dm->rank_x(),recvtag+2);
Dm->Comm.send(&localID[sendOffset_x],sendCount_x,Dm->rank_X(),sendtag+2);
Dm->Comm.Irecv(&nonlocalID[recvOffset_X], recvCount_X, Dm->rank_x(),
recvtag + 2);
Dm->Comm.send(&localID[sendOffset_x], sendCount_x, Dm->rank_X(),
sendtag + 2);
//printf("send X \n");
Dm->Comm.Irecv(&nonlocalID[recvOffset_x],recvCount_x,Dm->rank_X(),recvtag+3);
Dm->Comm.send(&localID[sendOffset_X],sendCount_X,Dm->rank_x(),sendtag+3);
Dm->Comm.Irecv(&nonlocalID[recvOffset_x], recvCount_x, Dm->rank_X(),
recvtag + 3);
Dm->Comm.send(&localID[sendOffset_X], sendCount_X, Dm->rank_x(),
sendtag + 3);
//printf("send y \n");
Dm->Comm.Irecv(&nonlocalID[recvOffset_Y],recvCount_Y,Dm->rank_y(),recvtag+4);
Dm->Comm.send(&localID[sendOffset_y],sendCount_y,Dm->rank_Y(),sendtag+4);
Dm->Comm.Irecv(&nonlocalID[recvOffset_Y], recvCount_Y, Dm->rank_y(),
recvtag + 4);
Dm->Comm.send(&localID[sendOffset_y], sendCount_y, Dm->rank_Y(),
sendtag + 4);
//printf("send Y \n");
Dm->Comm.Irecv(&nonlocalID[recvOffset_y],recvCount_y,Dm->rank_Y(),recvtag+5);
Dm->Comm.send(&localID[sendOffset_Y],sendCount_Y,Dm->rank_y(),sendtag+5);
Dm->Comm.Irecv(&nonlocalID[recvOffset_y], recvCount_y, Dm->rank_Y(),
recvtag + 5);
Dm->Comm.send(&localID[sendOffset_Y], sendCount_Y, Dm->rank_y(),
sendtag + 5);
//printf("send z \n");
Dm->Comm.Irecv(&nonlocalID[recvOffset_Z],recvCount_Z,Dm->rank_z(),recvtag+6);
Dm->Comm.send(&localID[sendOffset_z],sendCount_z,Dm->rank_Z(),sendtag+6);
Dm->Comm.Irecv(&nonlocalID[recvOffset_Z], recvCount_Z, Dm->rank_z(),
recvtag + 6);
Dm->Comm.send(&localID[sendOffset_z], sendCount_z, Dm->rank_Z(),
sendtag + 6);
//printf("send Z \n");
Dm->Comm.Irecv(&nonlocalID[recvOffset_z],recvCount_z,Dm->rank_Z(),recvtag+7);
Dm->Comm.send(&localID[sendOffset_Z],sendCount_Z,Dm->rank_z(),sendtag+7);
Dm->Comm.Irecv(&nonlocalID[recvOffset_z], recvCount_z, Dm->rank_Z(),
recvtag + 7);
Dm->Comm.send(&localID[sendOffset_Z], sendCount_Z, Dm->rank_z(),
sendtag + 7);
for (int idx = 0; idx < recvCount; idx++) {
double radius = morphRadius[idx];
@ -412,7 +431,9 @@ int Morphology::GetOverlaps(std::shared_ptr <Domain> Dm, signed char *id, const
for (jj = jmin; jj < jmax; jj++) {
for (ii = imin; ii < imax; ii++) {
int nn = kk * Nx * Ny + jj * Nx + ii;
double dsq = double((ii-i)*(ii-i)+(jj-j)*(jj-j)+(kk-k)*(kk-k));
double dsq =
double((ii - i) * (ii - i) + (jj - j) * (jj - j) +
(kk - k) * (kk - k));
if (id[nn] == ErodeLabel && dsq <= radius * radius) {
LocalNumber += 1.0;
id[nn] = NewLabel;
@ -428,7 +449,9 @@ int Morphology::GetOverlaps(std::shared_ptr <Domain> Dm, signed char *id, const
}
//***************************************************************************************
double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain> Dm, double VoidFraction, signed char ErodeLabel, signed char NewLabel){
double MorphOpen(DoubleArray &SignDist, signed char *id,
std::shared_ptr<Domain> Dm, double VoidFraction,
signed char ErodeLabel, signed char NewLabel) {
// SignDist is the distance to the object that you want to constaing the morphological opening
// VoidFraction is the the empty space where the object inst
// id is a labeled map
@ -453,7 +476,8 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
for (int i = 1; i < nx - 1; i++) {
n = k * nx * ny + j * nx + i;
// extract maximum distance for critical radius
if ( SignDist(i,j,k) > maxdist) maxdist=SignDist(i,j,k);
if (SignDist(i, j, k) > maxdist)
maxdist = SignDist(i, j, k);
if (id[n] == ErodeLabel) {
count += 1.0;
//id[n] = 2;
@ -469,10 +493,14 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
// total Global is the number of nodes in the pore-space
totalGlobal = Dm->Comm.sumReduce(count);
maxdistGlobal = Dm->Comm.sumReduce(maxdist);
double volume=double(nprocx*nprocy*nprocz)*double(nx-2)*double(ny-2)*double(nz-2);
double volume = double(nprocx * nprocy * nprocz) * double(nx - 2) *
double(ny - 2) * double(nz - 2);
double volume_fraction = totalGlobal / volume;
if (rank==0) printf("Volume fraction for morphological opening: %f \n",volume_fraction);
if (rank==0) printf("Maximum pore size: %f \n",maxdistGlobal);
if (rank == 0)
printf("Volume fraction for morphological opening: %f \n",
volume_fraction);
if (rank == 0)
printf("Maximum pore size: %f \n", maxdistGlobal);
final_void_fraction = volume_fraction; //initialize
int ii, jj, kk;
@ -496,8 +524,7 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
int numTry = 0;
int maxTry = 100;
while (void_fraction_new > VoidFraction && numTry < maxTry)
{
while (void_fraction_new > VoidFraction && numTry < maxTry) {
numTry++;
void_fraction_diff_old = void_fraction_diff_new;
void_fraction_old = void_fraction_new;
@ -507,7 +534,9 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
numTry = maxTry;
}
int Window = round(Rcrit_new);
if (Window == 0) Window = 1; // If Window = 0 at the begining, after the following process will have sw=1.0
if (Window == 0)
Window =
1; // If Window = 0 at the begining, after the following process will have sw=1.0
// and sw<Sw will be immediately broken
double LocalNumber = 0.f;
for (int k = 0; k < Nz; k++) {
@ -526,15 +555,17 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
for (jj = jmin; jj < jmax; jj++) {
for (ii = imin; ii < imax; ii++) {
int nn = kk * nx * ny + jj * nx + ii;
double dsq = double((ii-i)*(ii-i)+(jj-j)*(jj-j)+(kk-k)*(kk-k));
if (id[nn] == ErodeLabel && dsq <= Rcrit_new*Rcrit_new){
double dsq = double((ii - i) * (ii - i) +
(jj - j) * (jj - j) +
(kk - k) * (kk - k));
if (id[nn] == ErodeLabel &&
dsq <= Rcrit_new * Rcrit_new) {
LocalNumber += 1.0;
id[nn] = NewLabel;
}
}
}
}
}
// move on
}
@ -568,8 +599,7 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
printf("Final void fraction =%f\n", void_fraction_new);
printf("Final critical radius=%f\n", Rcrit_new);
}
}
else{
} else {
final_void_fraction = void_fraction_old;
if (rank == 0) {
printf("Final void fraction=%f\n", void_fraction_old);
@ -579,9 +609,9 @@ double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain>
return final_void_fraction;
}
//***************************************************************************************
double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain> Dm, double VoidFraction){
double MorphDrain(DoubleArray &SignDist, signed char *id,
std::shared_ptr<Domain> Dm, double VoidFraction) {
// SignDist is the distance to the object that you want to constaing the morphological opening
// VoidFraction is the the empty space where the object inst
// id is a labeled map
@ -601,7 +631,8 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
DoubleArray phase(nx, ny, nz);
IntArray phase_label(nx, ny, nz);
Array<char> ID(nx, ny, nz);
fillHalo<char> fillChar(Dm->Comm,Dm->rank_info,{nx-2,ny-2,nz-2},{1,1,1},0,1);
fillHalo<char> fillChar(Dm->Comm, Dm->rank_info, {nx - 2, ny - 2, nz - 2},
{1, 1, 1}, 0, 1);
Morphology Structure;
Structure.Initialize(Dm, SignDist);
@ -617,7 +648,8 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
for (int i = 1; i < nx - 1; i++) {
n = k * nx * ny + j * nx + i;
// extract maximum distance for critical radius
if ( SignDist(i,j,k) > maxdist) maxdist=SignDist(i,j,k);
if (SignDist(i, j, k) > maxdist)
maxdist = SignDist(i, j, k);
if (SignDist(i, j, k) > 0.0) {
count += 1.0;
id[n] = ErodeLabel;
@ -632,10 +664,14 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
// total Global is the number of nodes in the pore-space
totalGlobal = Dm->Comm.sumReduce(count);
maxdistGlobal = Dm->Comm.sumReduce(maxdist);
double volume=double(nprocx*nprocy*nprocz)*double(nx-2)*double(ny-2)*double(nz-2);
double volume = double(nprocx * nprocy * nprocz) * double(nx - 2) *
double(ny - 2) * double(nz - 2);
double volume_fraction = totalGlobal / volume;
if (rank==0) printf("Volume fraction for morphological opening: %f \n",volume_fraction);
if (rank==0) printf("Maximum pore size: %f \n",maxdistGlobal);
if (rank == 0)
printf("Volume fraction for morphological opening: %f \n",
volume_fraction);
if (rank == 0)
printf("Maximum pore size: %f \n", maxdistGlobal);
int ii, jj, kk;
int imin, jmin, kmin, imax, jmax, kmax;
@ -661,14 +697,15 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
FILE *DRAIN = fopen("morphdrain.csv", "w");
fprintf(DRAIN, "sw radius\n");
while (void_fraction_new > VoidFraction && Rcrit_new > 0.5)
{
while (void_fraction_new > VoidFraction && Rcrit_new > 0.5) {
void_fraction_diff_old = void_fraction_diff_new;
void_fraction_old = void_fraction_new;
Rcrit_old = Rcrit_new;
Rcrit_new -= deltaR * Rcrit_old;
int Window = round(Rcrit_new);
if (Window == 0) Window = 1; // If Window = 0 at the begining, after the following process will have sw=1.0
if (Window == 0)
Window =
1; // If Window = 0 at the begining, after the following process will have sw=1.0
// and sw<Sw will be immediately broken
double LocalNumber = 0.f;
for (int k = 1; k < Nz - 1; k++) {
@ -686,12 +723,17 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
for (kk = kmin; kk < kmax; kk++) {
for (jj = jmin; jj < jmax; jj++) {
for (ii = imin; ii < imax; ii++) {
double dsq = double((ii-i)*(ii-i)+(jj-j)*(jj-j)+(kk-k)*(kk-k));
if (ID(ii,jj,kk) == ErodeLabel && dsq <= (Rcrit_new+1)*(Rcrit_new+1)){
double dsq = double((ii - i) * (ii - i) +
(jj - j) * (jj - j) +
(kk - k) * (kk - k));
if (ID(ii, jj, kk) == ErodeLabel &&
dsq <=
(Rcrit_new + 1) * (Rcrit_new + 1)) {
LocalNumber += 1.0;
//id[nn]=1;
ID(ii, jj, kk) = NewLabel;
id[kk*Nx*Ny+jj*Nx+ii] = NewLabel;
id[kk * Nx * Ny + jj * Nx + ii] =
NewLabel;
}
}
}
@ -718,16 +760,17 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
for (int i = 0; i < nx; i++) {
if (ID(i, j, k) == NewLabel) {
phase(i, j, k) = 1.0;
}
else
} else
phase(i, j, k) = -1.0;
}
}
}
// Extract only the connected part of NWP
double vF=0.0; double vS=0.0;
ComputeGlobalBlobIDs(nx-2,ny-2,nz-2,Dm->rank_info,phase,SignDist,vF,vS,phase_label,Dm->Comm);
double vF = 0.0;
double vS = 0.0;
ComputeGlobalBlobIDs(nx - 2, ny - 2, nz - 2, Dm->rank_info, phase,
SignDist, vF, vS, phase_label, Dm->Comm);
Dm->Comm.barrier();
for (int k = 0; k < nz; k++) {
@ -770,8 +813,7 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
printf("Final void fraction =%f\n", void_fraction_new);
printf("Final critical radius=%f\n", Rcrit_new);
}
}
else{
} else {
final_void_fraction = void_fraction_old;
if (rank == 0) {
printf("Final void fraction=%f\n", void_fraction_old);
@ -794,8 +836,9 @@ double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain
}
//double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id, std::shared_ptr<Domain> Dm, double TargetGrowth)
double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id, std::shared_ptr<Domain> Dm, double TargetGrowth, double WallFactor)
{
double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
std::shared_ptr<Domain> Dm, double TargetGrowth,
double WallFactor) {
int Nx = Dm->Nx;
int Ny = Dm->Ny;
int Nz = Dm->Nz;
@ -815,14 +858,17 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
// Estimate morph_delta
double morph_delta = 0.0;
if (TargetGrowth > 0.0) morph_delta = 0.1;
else morph_delta = -0.1;
if (TargetGrowth > 0.0)
morph_delta = 0.1;
else
morph_delta = -0.1;
double morph_delta_previous = 0.0;
double GrowthEstimate = 0.0;
double GrowthPrevious = 0.0;
int COUNT_FOR_LOOP = 0;
double ERROR = 100.0;
if (rank == 0) printf("Estimate delta for growth=%f \n",TargetGrowth);
if (rank == 0)
printf("Estimate delta for growth=%f \n", TargetGrowth);
while (ERROR > 0.01 && COUNT_FOR_LOOP < 10) {
COUNT_FOR_LOOP++;
count = 0.0;
@ -832,9 +878,11 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
for (int i = 1; i < Nx - 1; i++) {
double walldist = BoundaryDist(i, j, k);
//double wallweight = 1.0 / (1+exp(-5.f*(walldist-1.f)));
double wallweight = WallFactor/ (1+exp(-5.f*(walldist-1.f)));
double wallweight =
WallFactor / (1 + exp(-5.f * (walldist - 1.f)));
//wallweight = 1.0;
if (fabs(wallweight*morph_delta) > MAX_DISPLACEMENT) MAX_DISPLACEMENT= fabs(wallweight*morph_delta);
if (fabs(wallweight * morph_delta) > MAX_DISPLACEMENT)
MAX_DISPLACEMENT = fabs(wallweight * morph_delta);
if (Dist(i, j, k) - wallweight * morph_delta < 0.0) {
count += 1.0;
@ -847,15 +895,20 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
GrowthEstimate = count - count_original;
ERROR = fabs((GrowthEstimate - TargetGrowth) / TargetGrowth);
if (rank == 0) printf(" delta=%f, growth=%f, max. displacement = %f \n",morph_delta, GrowthEstimate, MAX_DISPLACEMENT);
if (rank == 0)
printf(" delta=%f, growth=%f, max. displacement = %f \n",
morph_delta, GrowthEstimate, MAX_DISPLACEMENT);
// Now adjust morph_delta
if (fabs(GrowthEstimate - GrowthPrevious) > 0.0) {
double step_size = (TargetGrowth - GrowthEstimate)*(morph_delta - morph_delta_previous) / (GrowthEstimate - GrowthPrevious);
double step_size = (TargetGrowth - GrowthEstimate) *
(morph_delta - morph_delta_previous) /
(GrowthEstimate - GrowthPrevious);
GrowthPrevious = GrowthEstimate;
morph_delta_previous = morph_delta;
morph_delta += step_size;
}
if (morph_delta / morph_delta_previous > 2.0 ) morph_delta = morph_delta_previous*2.0;
if (morph_delta / morph_delta_previous > 2.0)
morph_delta = morph_delta_previous * 2.0;
//MAX_DISPLACEMENT *= max(TargetGrowth/GrowthEstimate,1.25);
@ -865,8 +918,7 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
morph_delta = 3.0;
COUNT_FOR_LOOP = 100; // exit loop if displacement is too large
}
}
else{
} else {
// object is shrinking
if (MAX_DISPLACEMENT > 1.0) {
morph_delta = -1.0;
@ -874,7 +926,8 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
}
}
}
if (rank == 0) printf("Final delta=%f \n",morph_delta);
if (rank == 0)
printf("Final delta=%f \n", morph_delta);
count = 0.0;
for (int k = 1; k < Nz - 1; k++) {
@ -883,10 +936,12 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
double walldist = BoundaryDist(i, j, k);
//double wallweight = 1.0 / (1+exp(-5.f*(walldist-1.f)));
//wallweight = 1.0;
double wallweight = WallFactor / (1+exp(-5.f*(walldist-1.f)));
double wallweight =
WallFactor / (1 + exp(-5.f * (walldist - 1.f)));
Dist(i, j, k) -= wallweight * morph_delta;
if (Dist(i,j,k) < 0.0) count+=1.0;
if (Dist(i, j, k) < 0.0)
count += 1.0;
}
}
}
@ -894,4 +949,3 @@ double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
return count;
}

View File

@ -3,9 +3,14 @@
#include "common/Domain.h"
#include "analysis/runAnalysis.h"
double MorphOpen(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain> Dm, double VoidFraction, signed char ErodeLabel, signed char ReplaceLabel);
double MorphDrain(DoubleArray &SignDist, signed char *id, std::shared_ptr<Domain> Dm, double VoidFraction);
double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id, std::shared_ptr<Domain> Dm, double TargetVol, double WallFactor);
double MorphOpen(DoubleArray &SignDist, signed char *id,
std::shared_ptr<Domain> Dm, double VoidFraction,
signed char ErodeLabel, signed char ReplaceLabel);
double MorphDrain(DoubleArray &SignDist, signed char *id,
std::shared_ptr<Domain> Dm, double VoidFraction);
double MorphGrow(DoubleArray &BoundaryDist, DoubleArray &Dist, Array<char> &id,
std::shared_ptr<Domain> Dm, double TargetVol,
double WallFactor);
#ifndef MORPHOLOGY_INC
#define MORPHOLOGY_INC
@ -41,7 +46,8 @@ public:
* @param ErodeLabel label to erode based on morphological operation
* @param NewLabel label to assign based on morphological operation
*/
int GetOverlaps(std::shared_ptr <Domain> Dm, signed char *id, const signed char ErodeLabel, const signed char NewLabel);
int GetOverlaps(std::shared_ptr<Domain> Dm, signed char *id,
const signed char ErodeLabel, const signed char NewLabel);
/*
* data structures to store non-local morphological information
@ -58,27 +64,39 @@ private:
//......................................................................................
int sendCount, recvCount;
//......................................................................................
int sendOffset_x, sendOffset_y, sendOffset_z, sendOffset_X, sendOffset_Y, sendOffset_Z;
int sendOffset_xy, sendOffset_yz, sendOffset_xz, sendOffset_Xy, sendOffset_Yz, sendOffset_xZ;
int sendOffset_xY, sendOffset_yZ, sendOffset_Xz, sendOffset_XY, sendOffset_YZ, sendOffset_XZ;
int sendOffset_x, sendOffset_y, sendOffset_z, sendOffset_X, sendOffset_Y,
sendOffset_Z;
int sendOffset_xy, sendOffset_yz, sendOffset_xz, sendOffset_Xy,
sendOffset_Yz, sendOffset_xZ;
int sendOffset_xY, sendOffset_yZ, sendOffset_Xz, sendOffset_XY,
sendOffset_YZ, sendOffset_XZ;
int sendOffset_xyz, sendOffset_XYZ, sendOffset_xYz, sendOffset_XyZ;
int sendOffset_Xyz, sendOffset_xYZ, sendOffset_xyZ, sendOffset_XYz;
//......................................................................................
int recvOffset_x, recvOffset_y, recvOffset_z, recvOffset_X, recvOffset_Y, recvOffset_Z;
int recvOffset_xy, recvOffset_yz, recvOffset_xz, recvOffset_Xy, recvOffset_Yz, recvOffset_xZ;
int recvOffset_xY, recvOffset_yZ, recvOffset_Xz, recvOffset_XY, recvOffset_YZ, recvOffset_XZ;
int recvOffset_x, recvOffset_y, recvOffset_z, recvOffset_X, recvOffset_Y,
recvOffset_Z;
int recvOffset_xy, recvOffset_yz, recvOffset_xz, recvOffset_Xy,
recvOffset_Yz, recvOffset_xZ;
int recvOffset_xY, recvOffset_yZ, recvOffset_Xz, recvOffset_XY,
recvOffset_YZ, recvOffset_XZ;
int recvOffset_xyz, recvOffset_XYZ, recvOffset_xYz, recvOffset_XyZ;
int recvOffset_Xyz, recvOffset_xYZ, recvOffset_xyZ, recvOffset_XYz;
//......................................................................................
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y, sendCount_Z;
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz, sendCount_xZ;
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ, sendCount_XZ;
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y,
sendCount_Z;
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz,
sendCount_xZ;
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ,
sendCount_XZ;
int sendCount_xyz, sendCount_XYZ, sendCount_xYz, sendCount_XyZ;
int sendCount_Xyz, sendCount_xYZ, sendCount_xyZ, sendCount_XYz;
//......................................................................................
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y, recvCount_Z;
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz, recvCount_xZ;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ, recvCount_XZ;
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y,
recvCount_Z;
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz,
recvCount_xZ;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ,
recvCount_XZ;
int recvCount_xyz, recvCount_XYZ, recvCount_xYz, recvCount_XyZ;
int recvCount_Xyz, recvCount_xYZ, recvCount_xyZ, recvCount_XYz;
//......................................................................................
@ -87,12 +105,18 @@ private:
//......................................................................................
// Communication buffers
signed char *sendID_x, *sendID_y, *sendID_z, *sendID_X, *sendID_Y, *sendID_Z;
signed char *sendID_xy, *sendID_yz, *sendID_xz, *sendID_Xy, *sendID_Yz, *sendID_xZ;
signed char *sendID_xY, *sendID_yZ, *sendID_Xz, *sendID_XY, *sendID_YZ, *sendID_XZ;
signed char *recvID_x, *recvID_y, *recvID_z, *recvID_X, *recvID_Y, *recvID_Z;
signed char *recvID_xy, *recvID_yz, *recvID_xz, *recvID_Xy, *recvID_Yz, *recvID_xZ;
signed char *recvID_xY, *recvID_yZ, *recvID_Xz, *recvID_XY, *recvID_YZ, *recvID_XZ;
signed char *sendID_x, *sendID_y, *sendID_z, *sendID_X, *sendID_Y,
*sendID_Z;
signed char *sendID_xy, *sendID_yz, *sendID_xz, *sendID_Xy, *sendID_Yz,
*sendID_xZ;
signed char *sendID_xY, *sendID_yZ, *sendID_Xz, *sendID_XY, *sendID_YZ,
*sendID_XZ;
signed char *recvID_x, *recvID_y, *recvID_z, *recvID_X, *recvID_Y,
*recvID_Z;
signed char *recvID_xy, *recvID_yz, *recvID_xz, *recvID_Xy, *recvID_Yz,
*recvID_xZ;
signed char *recvID_xY, *recvID_yZ, *recvID_Xz, *recvID_XY, *recvID_YZ,
*recvID_XZ;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// Run the analysis, blob identification, and write restart files
#include "analysis/runAnalysis.h"
#include "analysis/analysis.h"
@ -12,39 +28,32 @@
#include "ProfilerApp.h"
AnalysisType &operator|=( AnalysisType &lhs, AnalysisType rhs )
{
lhs = static_cast<AnalysisType>( static_cast<std::underlying_type<AnalysisType>::type>( lhs ) |
AnalysisType &operator|=(AnalysisType &lhs, AnalysisType rhs) {
lhs = static_cast<AnalysisType>(
static_cast<std::underlying_type<AnalysisType>::type>(lhs) |
static_cast<std::underlying_type<AnalysisType>::type>(rhs));
return lhs;
}
bool matches( AnalysisType x, AnalysisType y )
{
bool matches(AnalysisType x, AnalysisType y) {
return (static_cast<std::underlying_type<AnalysisType>::type>(x) &
static_cast<std::underlying_type<AnalysisType>::type>(y)) != 0;
}
// Create a shared_ptr to an array of values
template <class TYPE>
static inline std::shared_ptr<TYPE> make_shared_array( size_t N )
{
return std::shared_ptr<TYPE>( new TYPE[N], []( const TYPE *p ) { delete[] p; } );
static inline std::shared_ptr<TYPE> make_shared_array(size_t N) {
return std::shared_ptr<TYPE>(new TYPE[N],
[](const TYPE *p) { delete[] p; });
}
// Helper class to write the restart file from a seperate thread
class WriteRestartWorkItem : public ThreadPool::WorkItemRet<void>
{
class WriteRestartWorkItem : public ThreadPool::WorkItemRet<void> {
public:
WriteRestartWorkItem( const std::string &filename_, std::shared_ptr<double> cDen_,
WriteRestartWorkItem(const std::string &filename_,
std::shared_ptr<double> cDen_,
std::shared_ptr<double> cfq_, int N_)
: filename( filename_ ), cfq( cfq_ ), cDen( cDen_ ), N( N_ )
{
}
virtual void run()
{
: filename(filename_), cfq(cfq_), cDen(cDen_), N(N_) {}
virtual void run() {
PROFILE_START("Save Checkpoint", 1);
double value;
ofstream File(filename, ios::binary);
@ -73,42 +82,32 @@ private:
const int N;
};
// Helper class to compute the blob ids
typedef std::shared_ptr<std::pair<int, IntArray>> BlobIDstruct;
typedef std::shared_ptr<std::vector<BlobIDType>> BlobIDList;
static const std::string id_map_filename = "lbpm_id_map.txt";
class BlobIdentificationWorkItem1 : public ThreadPool::WorkItemRet<void>
{
class BlobIdentificationWorkItem1 : public ThreadPool::WorkItemRet<void> {
public:
BlobIdentificationWorkItem1(int timestep_, int Nx_, int Ny_, int Nz_,
const RankInfoStruct &rank_info_, std::shared_ptr<const DoubleArray> phase_,
const DoubleArray &dist_, BlobIDstruct last_id_, BlobIDstruct new_index_,
BlobIDstruct new_id_, BlobIDList new_list_, runAnalysis::commWrapper &&comm_ )
: timestep( timestep_ ),
Nx( Nx_ ),
Ny( Ny_ ),
Nz( Nz_ ),
rank_info( rank_info_ ),
phase( phase_ ),
dist( dist_ ),
last_id( last_id_ ),
new_index( new_index_ ),
new_id( new_id_ ),
new_list( new_list_ ),
comm( std::move( comm_ ) )
{
}
const RankInfoStruct &rank_info_,
std::shared_ptr<const DoubleArray> phase_,
const DoubleArray &dist_, BlobIDstruct last_id_,
BlobIDstruct new_index_, BlobIDstruct new_id_,
BlobIDList new_list_,
runAnalysis::commWrapper &&comm_)
: timestep(timestep_), Nx(Nx_), Ny(Ny_), Nz(Nz_), rank_info(rank_info_),
phase(phase_), dist(dist_), last_id(last_id_), new_index(new_index_),
new_id(new_id_), new_list(new_list_), comm(std::move(comm_)) {}
~BlobIdentificationWorkItem1() {}
virtual void run()
{
virtual void run() {
// Compute the global blob id and compare to the previous version
PROFILE_START("Identify blobs", 1);
double vF = 0.0;
double vS = -1.0; // one voxel buffer region around solid
IntArray &ids = new_index->second;
new_index->first = ComputeGlobalBlobIDs(
Nx - 2, Ny - 2, Nz - 2, rank_info, *phase, dist, vF, vS, ids, comm.comm );
new_index->first =
ComputeGlobalBlobIDs(Nx - 2, Ny - 2, Nz - 2, rank_info, *phase,
dist, vF, vS, ids, comm.comm);
PROFILE_STOP("Identify blobs", 1);
}
@ -123,30 +122,20 @@ private:
BlobIDList new_list;
runAnalysis::commWrapper comm;
};
class BlobIdentificationWorkItem2 : public ThreadPool::WorkItemRet<void>
{
class BlobIdentificationWorkItem2 : public ThreadPool::WorkItemRet<void> {
public:
BlobIdentificationWorkItem2(int timestep_, int Nx_, int Ny_, int Nz_,
const RankInfoStruct &rank_info_, std::shared_ptr<const DoubleArray> phase_,
const DoubleArray &dist_, BlobIDstruct last_id_, BlobIDstruct new_index_,
BlobIDstruct new_id_, BlobIDList new_list_, runAnalysis::commWrapper &&comm_ )
: timestep( timestep_ ),
Nx( Nx_ ),
Ny( Ny_ ),
Nz( Nz_ ),
rank_info( rank_info_ ),
phase( phase_ ),
dist( dist_ ),
last_id( last_id_ ),
new_index( new_index_ ),
new_id( new_id_ ),
new_list( new_list_ ),
comm( std::move( comm_ ) )
{
}
const RankInfoStruct &rank_info_,
std::shared_ptr<const DoubleArray> phase_,
const DoubleArray &dist_, BlobIDstruct last_id_,
BlobIDstruct new_index_, BlobIDstruct new_id_,
BlobIDList new_list_,
runAnalysis::commWrapper &&comm_)
: timestep(timestep_), Nx(Nx_), Ny(Ny_), Nz(Nz_), rank_info(rank_info_),
phase(phase_), dist(dist_), last_id(last_id_), new_index(new_index_),
new_id(new_id_), new_list(new_list_), comm(std::move(comm_)) {}
~BlobIdentificationWorkItem2() {}
virtual void run()
{
virtual void run() {
// Compute the global blob id and compare to the previous version
PROFILE_START("Identify blobs maps", 1);
const IntArray &ids = new_index->second;
@ -156,7 +145,8 @@ public:
if (last_id.get() != NULL) {
// Compute the timestep-timestep map
const IntArray &old_ids = last_id->second;
ID_map_struct map = computeIDMap( Nx, Ny, Nz, old_ids, ids, comm.comm );
ID_map_struct map =
computeIDMap(Nx, Ny, Nz, old_ids, ids, comm.comm);
// Renumber the current timestep's ids
getNewIDs(map, max_id, *new_list);
renumberIDs(*new_list, new_id->second);
@ -182,25 +172,18 @@ private:
runAnalysis::commWrapper comm;
};
// Helper class to write the vis file from a thread
class WriteVisWorkItem : public ThreadPool::WorkItemRet<void>
{
class WriteVisWorkItem : public ThreadPool::WorkItemRet<void> {
public:
WriteVisWorkItem(int timestep_, std::vector<IO::MeshDataStruct> &visData_,
TwoPhase &Avgerages_, std::array<int, 3> n_, RankInfoStruct rank_info_,
TwoPhase &Avgerages_, std::array<int, 3> n_,
RankInfoStruct rank_info_,
runAnalysis::commWrapper &&comm_)
: timestep( timestep_ ),
visData( visData_ ),
Averages( Avgerages_ ),
n( std::move( n_ ) ),
rank_info( std::move( rank_info_ ) ),
comm( std::move( comm_ ) )
{
}
: timestep(timestep_), visData(visData_), Averages(Avgerages_),
n(std::move(n_)), rank_info(std::move(rank_info_)),
comm(std::move(comm_)) {}
~WriteVisWorkItem() {}
virtual void run()
{
virtual void run() {
PROFILE_START("Save Vis", 1);
fillHalo<double> fillData(comm.comm, rank_info, n, {1, 1, 1}, 0, 1);
@ -246,24 +229,17 @@ private:
};
// Helper class to write the vis file from a thread
class IOWorkItem : public ThreadPool::WorkItemRet<void>
{
class IOWorkItem : public ThreadPool::WorkItemRet<void> {
public:
IOWorkItem(int timestep_, std::shared_ptr<Database> input_db_,
std::vector<IO::MeshDataStruct> &visData_, SubPhase &Averages_, std::array<int, 3> n_,
RankInfoStruct rank_info_, runAnalysis::commWrapper &&comm_ )
: timestep( timestep_ ),
input_db( input_db_ ),
visData( visData_ ),
Averages( Averages_ ),
n( std::move( n_ ) ),
rank_info( std::move( rank_info_ ) ),
comm( std::move( comm_ ) )
{
}
std::vector<IO::MeshDataStruct> &visData_, SubPhase &Averages_,
std::array<int, 3> n_, RankInfoStruct rank_info_,
runAnalysis::commWrapper &&comm_)
: timestep(timestep_), input_db(input_db_), visData(visData_),
Averages(Averages_), n(std::move(n_)),
rank_info(std::move(rank_info_)), comm(std::move(comm_)) {}
~IOWorkItem() {}
virtual void run()
{
virtual void run() {
PROFILE_START("Save Vis", 1);
auto color_db = input_db->getDatabase("Color");
@ -337,25 +313,16 @@ private:
runAnalysis::commWrapper comm;
};
// Helper class to run the analysis from within a thread
// Note: Averages will be modified after the constructor is called
class AnalysisWorkItem : public ThreadPool::WorkItemRet<void>
{
class AnalysisWorkItem : public ThreadPool::WorkItemRet<void> {
public:
AnalysisWorkItem( AnalysisType type_, int timestep_, TwoPhase &Averages_, BlobIDstruct ids,
BlobIDList id_list_, double beta_ )
: type( type_ ),
timestep( timestep_ ),
Averages( Averages_ ),
blob_ids( ids ),
id_list( id_list_ ),
beta( beta_ )
{
}
AnalysisWorkItem(AnalysisType type_, int timestep_, TwoPhase &Averages_,
BlobIDstruct ids, BlobIDList id_list_, double beta_)
: type(type_), timestep(timestep_), Averages(Averages_), blob_ids(ids),
id_list(id_list_), beta(beta_) {}
~AnalysisWorkItem() {}
virtual void run()
{
virtual void run() {
Averages.NumberComponents_NWP = blob_ids->first;
Averages.Label_NWP = blob_ids->second;
Averages.Label_NWP_map = *id_list;
@ -369,8 +336,10 @@ public:
Averages.Initialize();
Averages.ComputeDelPhi();
Averages.ColorToSignedDistance(beta, Averages.Phase, Averages.SDn);
Averages.ColorToSignedDistance( beta, Averages.Phase_tminus, Averages.Phase_tminus );
Averages.ColorToSignedDistance( beta, Averages.Phase_tplus, Averages.Phase_tplus );
Averages.ColorToSignedDistance(beta, Averages.Phase_tminus,
Averages.Phase_tminus);
Averages.ColorToSignedDistance(beta, Averages.Phase_tplus,
Averages.Phase_tplus);
Averages.UpdateMeshValues();
Averages.ComputeLocal();
Averages.Reduce();
@ -393,23 +362,14 @@ private:
double beta;
};
class TCATWorkItem : public ThreadPool::WorkItemRet<void>
{
class TCATWorkItem : public ThreadPool::WorkItemRet<void> {
public:
TCATWorkItem( AnalysisType type_, int timestep_, TwoPhase &Averages_, BlobIDstruct ids,
BlobIDList id_list_, double beta_ )
: type( type_ ),
timestep( timestep_ ),
Averages( Averages_ ),
blob_ids( ids ),
id_list( id_list_ ),
beta( beta_ )
{
}
TCATWorkItem(AnalysisType type_, int timestep_, TwoPhase &Averages_,
BlobIDstruct ids, BlobIDList id_list_, double beta_)
: type(type_), timestep(timestep_), Averages(Averages_), blob_ids(ids),
id_list(id_list_), beta(beta_) {}
~TCATWorkItem() {}
virtual void run()
{
virtual void run() {
Averages.NumberComponents_NWP = blob_ids->first;
Averages.Label_NWP = blob_ids->second;
Averages.Label_NWP_map = *id_list;
@ -423,8 +383,10 @@ public:
Averages.Initialize();
Averages.ComputeDelPhi();
Averages.ColorToSignedDistance(beta, Averages.Phase, Averages.SDn);
Averages.ColorToSignedDistance( beta, Averages.Phase_tminus, Averages.Phase_tminus );
Averages.ColorToSignedDistance( beta, Averages.Phase_tplus, Averages.Phase_tplus );
Averages.ColorToSignedDistance(beta, Averages.Phase_tminus,
Averages.Phase_tminus);
Averages.ColorToSignedDistance(beta, Averages.Phase_tplus,
Averages.Phase_tplus);
Averages.UpdateMeshValues();
Averages.ComputeLocal();
Averages.Reduce();
@ -443,23 +405,15 @@ private:
double beta;
};
class GanglionTrackingWorkItem : public ThreadPool::WorkItemRet<void>
{
class GanglionTrackingWorkItem : public ThreadPool::WorkItemRet<void> {
public:
GanglionTrackingWorkItem( AnalysisType type_, int timestep_, TwoPhase &Averages_,
BlobIDstruct ids, BlobIDList id_list_, double beta_ )
: type( type_ ),
timestep( timestep_ ),
Averages( Averages_ ),
blob_ids( ids ),
id_list( id_list_ ),
beta( beta_ )
{
}
GanglionTrackingWorkItem(AnalysisType type_, int timestep_,
TwoPhase &Averages_, BlobIDstruct ids,
BlobIDList id_list_, double beta_)
: type(type_), timestep(timestep_), Averages(Averages_), blob_ids(ids),
id_list(id_list_), beta(beta_) {}
~GanglionTrackingWorkItem() {}
virtual void run()
{
virtual void run() {
Averages.NumberComponents_NWP = blob_ids->first;
Averages.Label_NWP = blob_ids->second;
Averages.Label_NWP_map = *id_list;
@ -473,8 +427,10 @@ public:
Averages.Initialize();
Averages.ComputeDelPhi();
Averages.ColorToSignedDistance(beta, Averages.Phase, Averages.SDn);
Averages.ColorToSignedDistance( beta, Averages.Phase_tminus, Averages.Phase_tminus );
Averages.ColorToSignedDistance( beta, Averages.Phase_tplus, Averages.Phase_tplus );
Averages.ColorToSignedDistance(beta, Averages.Phase_tminus,
Averages.Phase_tminus);
Averages.ColorToSignedDistance(beta, Averages.Phase_tplus,
Averages.Phase_tplus);
Averages.UpdateMeshValues();
Averages.ComponentAverages();
Averages.SortBlobs();
@ -493,17 +449,12 @@ private:
double beta;
};
class BasicWorkItem : public ThreadPool::WorkItemRet<void>
{
class BasicWorkItem : public ThreadPool::WorkItemRet<void> {
public:
BasicWorkItem(AnalysisType type_, int timestep_, SubPhase &Averages_)
: type( type_ ), timestep( timestep_ ), Averages( Averages_ )
{
}
: type(type_), timestep(timestep_), Averages(Averages_) {}
~BasicWorkItem() {}
virtual void run()
{
virtual void run() {
if (matches(type, AnalysisType::CopyPhaseIndicator)) {
// Averages.ColorToSignedDistance(beta,Averages.Phase,Averages.Phase_tplus);
@ -523,16 +474,12 @@ private:
double beta;
};
class SubphaseWorkItem : public ThreadPool::WorkItemRet<void>
{
class SubphaseWorkItem : public ThreadPool::WorkItemRet<void> {
public:
SubphaseWorkItem(AnalysisType type_, int timestep_, SubPhase &Averages_)
: type( type_ ), timestep( timestep_ ), Averages( Averages_ )
{
}
: type(type_), timestep(timestep_), Averages(Averages_) {}
~SubphaseWorkItem() {}
virtual void run()
{
virtual void run() {
PROFILE_START("Compute subphase", 1);
Averages.Full();
@ -548,29 +495,23 @@ private:
double beta;
};
/******************************************************************
* MPI comm wrapper for use with analysis *
******************************************************************/
runAnalysis::commWrapper::commWrapper(
int tag_, const Utilities::MPI &comm_, runAnalysis *analysis_ )
: comm( comm_ ), tag( tag_ ), analysis( analysis_ )
{
}
runAnalysis::commWrapper::commWrapper(int tag_, const Utilities::MPI &comm_,
runAnalysis *analysis_)
: comm(comm_), tag(tag_), analysis(analysis_) {}
runAnalysis::commWrapper::commWrapper(commWrapper &&rhs)
: comm( rhs.comm ), tag( rhs.tag ), analysis( rhs.analysis )
{
: comm(rhs.comm), tag(rhs.tag), analysis(rhs.analysis) {
rhs.tag = -1;
}
runAnalysis::commWrapper::~commWrapper()
{
runAnalysis::commWrapper::~commWrapper() {
if (tag == -1)
return;
comm.barrier();
analysis->d_comm_used[tag] = false;
}
runAnalysis::commWrapper runAnalysis::getComm()
{
runAnalysis::commWrapper runAnalysis::getComm() {
// Get a tag from root
int tag = -1;
if (d_rank == 0) {
@ -590,24 +531,23 @@ runAnalysis::commWrapper runAnalysis::getComm()
return commWrapper(tag, d_comms[tag], this);
}
/******************************************************************
* Constructor/Destructors *
******************************************************************/
runAnalysis::runAnalysis( std::shared_ptr<Database> input_db, const RankInfoStruct &rank_info,
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm, std::shared_ptr<Domain> Dm, int Np,
bool Regular, IntArray Map )
: d_Np( Np ),
d_regular( Regular ),
d_rank_info( rank_info ),
d_Map( Map ),
d_comm( Dm->Comm.dup() ),
d_ScaLBL_Comm( ScaLBL_Comm )
{
runAnalysis::runAnalysis(std::shared_ptr<Database> input_db,
const RankInfoStruct &rank_info,
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm,
std::shared_ptr<Domain> Dm, int Np, bool Regular,
IntArray Map)
: d_Np(Np), d_regular(Regular), d_rank_info(rank_info), d_Map(Map),
d_comm(Dm->Comm.dup()), d_ScaLBL_Comm(ScaLBL_Comm) {
auto db = input_db->getDatabase("Analysis");
auto vis_db = input_db->getDatabase("Visualization");
/* set the I/O format */
format = vis_db->getWithDefault<string>("format", "silo");
// Ids of work items to use for dependencies
ThreadPool::thread_id_t d_wait_blobID;
ThreadPool::thread_id_t d_wait_analysis;
@ -636,17 +576,22 @@ runAnalysis::runAnalysis( std::shared_ptr<Database> input_db, const RankInfoStru
d_visualization_interval = db->getScalar<int>("visualization_interval");
}
if (db->keyExists("subphase_analysis_interval")) {
d_subphase_analysis_interval = db->getScalar<int>( "subphase_analysis_interval" );
d_subphase_analysis_interval =
db->getScalar<int>("subphase_analysis_interval");
}
auto restart_file = db->getWithDefault<std::string>( "restart_file", "Restart");
auto restart_file =
db->getWithDefault<std::string>("restart_file", "Restart");
d_restartFile = restart_file + "." + rankString;
d_rank = d_comm.getRank();
writeIDMap(ID_map_struct(), 0, id_map_filename);
// Initialize IO for silo
IO::initialize( "", "silo", "false" );
//std::string format = "silo";
format = vis_db->getWithDefault<string>("format", "silo");
IO::initialize("", format, "false");
// Create the MeshDataStruct
d_meshData.resize(1);
@ -720,7 +665,6 @@ runAnalysis::runAnalysis( std::shared_ptr<Database> input_db, const RankInfoStru
d_meshData[0].vars.push_back(BlobIDVar);
}
// Initialize the comms
for (int i = 0; i < 1024; i++)
d_comm_used[i] = false;
@ -777,22 +721,29 @@ runAnalysis::runAnalysis( ScaLBL_ColorModel &ColorModel)
d_visualization_interval = db->getScalar<int>("visualization_interval");
}
if (db->keyExists("subphase_analysis_interval")) {
d_subphase_analysis_interval = db->getScalar<int>( "subphase_analysis_interval" );
d_subphase_analysis_interval =
db->getScalar<int>("subphase_analysis_interval");
}
auto restart_file = db->getWithDefault<std::string>( "restart_file", "Restart");
auto restart_file =
db->getWithDefault<std::string>("restart_file", "Restart");
d_restartFile = restart_file + "." + rankString;
d_rank = d_comm.getRank();
writeIDMap(ID_map_struct(), 0, id_map_filename);
// Initialize IO for silo
IO::initialize( "", "silo", "false" );
//std::string format = "silo";
format = vis_db->getWithDefault<string>("format", "silo");
IO::initialize("", format, "false");
// Create the MeshDataStruct
d_meshData.resize(1);
d_meshData[0].meshName = "domain";
d_meshData[0].mesh = std::make_shared<IO::DomainMesh>(
d_rank_info, d_n[0], d_n[1], d_n[2], ColorModel.Dm->Lx, ColorModel.Dm->Ly, ColorModel.Dm->Lz );
d_rank_info, d_n[0], d_n[1], d_n[2], ColorModel.Dm->Lx,
ColorModel.Dm->Ly, ColorModel.Dm->Lz);
auto PhaseVar = std::make_shared<IO::Variable>();
auto PressVar = std::make_shared<IO::Variable>();
auto VxVar = std::make_shared<IO::Variable>();
@ -851,7 +802,6 @@ runAnalysis::runAnalysis( ScaLBL_ColorModel &ColorModel)
d_meshData[0].vars.push_back(BlobIDVar);
}
// Initialize the comms
for (int i = 0; i < 1024; i++)
d_comm_used[i] = false;
@ -860,13 +810,11 @@ runAnalysis::runAnalysis( ScaLBL_ColorModel &ColorModel)
auto method = db->getWithDefault<std::string>("load_balance", "default");
createThreads(method, N_threads);
}
runAnalysis::~runAnalysis()
{
runAnalysis::~runAnalysis() {
// Finish processing analysis
finish();
}
void runAnalysis::finish()
{
void runAnalysis::finish() {
PROFILE_START("finish");
// Wait for the work items to finish
d_tpool.wait_pool_finished();
@ -881,12 +829,10 @@ void runAnalysis::finish()
PROFILE_STOP("finish");
}
/******************************************************************
* Set the thread affinities *
******************************************************************/
void print( const std::vector<int> &ids )
{
void print(const std::vector<int> &ids) {
if (ids.empty())
return;
printf("%i", ids[0]);
@ -894,16 +840,16 @@ void print( const std::vector<int> &ids )
printf(", %i", ids[i]);
printf("\n");
}
void runAnalysis::createThreads( const std::string &method, int N_threads )
{
void runAnalysis::createThreads(const std::string &method, int N_threads) {
// Check if we are not using analysis threads
if (method == "none")
return;
// Check if we have thread support
auto thread_support = Utilities::MPI::queryThreadSupport();
if ( thread_support != Utilities::MPI::ThreadSupport::MULTIPLE && N_threads > 0 )
std::cerr
<< "Warning: Failed to start MPI with necessary thread support, errors may occur\n";
if (thread_support != Utilities::MPI::ThreadSupport::MULTIPLE &&
N_threads > 0)
std::cerr << "Warning: Failed to start MPI with necessary thread "
"support, errors may occur\n";
// Create the threads
const auto cores = d_tpool.getProcessAffinity();
if (N_threads == 0) {
@ -934,12 +880,10 @@ void runAnalysis::createThreads( const std::string &method, int N_threads )
}
}
/******************************************************************
* Check which analysis we want to perform *
******************************************************************/
AnalysisType runAnalysis::computeAnalysisType( int timestep )
{
AnalysisType runAnalysis::computeAnalysisType(int timestep) {
AnalysisType type = AnalysisType::AnalyzeNone;
if (timestep % d_analysis_interval + 8 == d_analysis_interval) {
// Copy the phase indicator field for the earlier timestep
@ -982,13 +926,12 @@ AnalysisType runAnalysis::computeAnalysisType( int timestep )
return type;
}
/******************************************************************
* Run the analysis *
******************************************************************/
void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhase &Averages,
const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den )
{
void runAnalysis::run(int timestep, std::shared_ptr<Database> input_db,
TwoPhase &Averages, const double *Phi, double *Pressure,
double *Velocity, double *fq, double *Den) {
int N = d_N[0] * d_N[1] * d_N[2];
NULL_USE(N);
NULL_USE(Phi);
@ -1049,14 +992,16 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
if (d_regular)
d_ScaLBL_Comm->RegularLayout(d_Map, Phi, Averages.Phase_tplus);
else
ScaLBL_CopyToHost( Averages.Phase_tplus.data(), Phi, N * sizeof( double ) );
ScaLBL_CopyToHost(Averages.Phase_tplus.data(), Phi,
N * sizeof(double));
// memcpy(Averages.Phase_tplus.data(),phase->data(),N*sizeof(double));
}
if (timestep % d_analysis_interval == 0) {
if (d_regular)
d_ScaLBL_Comm->RegularLayout(d_Map, Phi, Averages.Phase_tminus);
else
ScaLBL_CopyToHost( Averages.Phase_tminus.data(), Phi, N * sizeof( double ) );
ScaLBL_CopyToHost(Averages.Phase_tminus.data(), Phi,
N * sizeof(double));
// memcpy(Averages.Phase_tminus.data(),phase->data(),N*sizeof(double));
}
// if ( matches(type,AnalysisType::CopySimState) ) {
@ -1079,7 +1024,8 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
d_ScaLBL_Comm->RegularLayout(d_Map, Pressure, Averages.Press);
d_ScaLBL_Comm->RegularLayout(d_Map, &Velocity[0], Averages.Vel_x);
d_ScaLBL_Comm->RegularLayout(d_Map, &Velocity[d_Np], Averages.Vel_y);
d_ScaLBL_Comm->RegularLayout( d_Map, &Velocity[2 * d_Np], Averages.Vel_z );
d_ScaLBL_Comm->RegularLayout(d_Map, &Velocity[2 * d_Np],
Averages.Vel_z);
PROFILE_STOP("Copy-State", 1);
}
std::shared_ptr<double> cfq, cDen;
@ -1101,13 +1047,17 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
else
ScaLBL_CopyToHost(phase->data(), Phi, N * sizeof(double));
auto new_index = std::make_shared<std::pair<int, IntArray>>( 0, IntArray() );
auto new_ids = std::make_shared<std::pair<int, IntArray>>( 0, IntArray() );
auto new_index =
std::make_shared<std::pair<int, IntArray>>(0, IntArray());
auto new_ids =
std::make_shared<std::pair<int, IntArray>>(0, IntArray());
auto new_list = std::make_shared<std::vector<BlobIDType>>();
auto work1 = new BlobIdentificationWorkItem1( timestep, d_N[0], d_N[1], d_N[2], d_rank_info,
phase, Averages.SDs, d_last_ids, new_index, new_ids, new_list, getComm() );
auto work2 = new BlobIdentificationWorkItem2( timestep, d_N[0], d_N[1], d_N[2], d_rank_info,
phase, Averages.SDs, d_last_ids, new_index, new_ids, new_list, getComm() );
auto work1 = new BlobIdentificationWorkItem1(
timestep, d_N[0], d_N[1], d_N[2], d_rank_info, phase, Averages.SDs,
d_last_ids, new_index, new_ids, new_list, getComm());
auto work2 = new BlobIdentificationWorkItem2(
timestep, d_N[0], d_N[1], d_N[2], d_rank_info, phase, Averages.SDs,
d_last_ids, new_index, new_ids, new_list, getComm());
work1->add_dependency(d_wait_blobID);
work2->add_dependency(d_tpool.add_work(work1));
d_wait_blobID = d_tpool.add_work(work2);
@ -1120,11 +1070,12 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
// if (timestep%d_restart_interval==0){
// if ( matches(type,AnalysisType::ComputeAverages) ) {
if (timestep % d_analysis_interval == 0) {
auto work =
new AnalysisWorkItem( type, timestep, Averages, d_last_index, d_last_id_map, d_beta );
auto work = new AnalysisWorkItem(type, timestep, Averages, d_last_index,
d_last_id_map, d_beta);
work->add_dependency(d_wait_blobID);
work->add_dependency(d_wait_analysis);
work->add_dependency( d_wait_vis ); // Make sure we are done using analysis before modifying
work->add_dependency(
d_wait_vis); // Make sure we are done using analysis before modifying
d_wait_analysis = d_tpool.add_work(work);
}
@ -1139,7 +1090,8 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
OutStream.close();
}
// Write the restart file (using a seperate thread)
auto work = new WriteRestartWorkItem( d_restartFile.c_str(), cDen, cfq, d_Np );
auto work =
new WriteRestartWorkItem(d_restartFile.c_str(), cDen, cfq, d_Np);
work->add_dependency(d_wait_restart);
d_wait_restart = d_tpool.add_work(work);
}
@ -1148,8 +1100,8 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
// if ( matches(type,AnalysisType::CreateRestart) ) {
if (timestep % d_restart_interval == 0) {
// Write the vis files
auto work =
new WriteVisWorkItem( timestep, d_meshData, Averages, d_n, d_rank_info, getComm() );
auto work = new WriteVisWorkItem(timestep, d_meshData, Averages, d_n,
d_rank_info, getComm());
work->add_dependency(d_wait_blobID);
work->add_dependency(d_wait_analysis);
work->add_dependency(d_wait_vis);
@ -1158,13 +1110,12 @@ void runAnalysis::run( int timestep, std::shared_ptr<Database> input_db, TwoPhas
PROFILE_STOP("run");
}
/******************************************************************
* Run the analysis *
******************************************************************/
void runAnalysis::basic( int timestep, std::shared_ptr<Database> input_db, SubPhase &Averages,
const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den )
{
void runAnalysis::basic(int timestep, std::shared_ptr<Database> input_db,
SubPhase &Averages, const double *Phi, double *Pressure,
double *Velocity, double *fq, double *Den) {
int Nx = d_N[0];
int Ny = d_N[1];
int Nz = d_N[2];
@ -1213,7 +1164,8 @@ void runAnalysis::basic( int timestep, std::shared_ptr<Database> input_db, SubPh
d_ScaLBL_Comm->RegularLayout(d_Map, &Den[d_Np], Averages.Rho_w);
d_ScaLBL_Comm->RegularLayout(d_Map, &Velocity[0], Averages.Vel_x);
d_ScaLBL_Comm->RegularLayout(d_Map, &Velocity[d_Np], Averages.Vel_y);
d_ScaLBL_Comm->RegularLayout( d_Map, &Velocity[2 * d_Np], Averages.Vel_z );
d_ScaLBL_Comm->RegularLayout(d_Map, &Velocity[2 * d_Np],
Averages.Vel_z);
PROFILE_STOP("Copy-State", 1);
}
PROFILE_STOP("Copy data to host");
@ -1256,15 +1208,16 @@ void runAnalysis::basic( int timestep, std::shared_ptr<Database> input_db, SubPh
OutStream.close();
}
// Write the restart file (using a seperate thread)
auto work1 = new WriteRestartWorkItem( d_restartFile.c_str(), cDen, cfq, d_Np );
auto work1 =
new WriteRestartWorkItem(d_restartFile.c_str(), cDen, cfq, d_Np);
work1->add_dependency(d_wait_restart);
d_wait_restart = d_tpool.add_work(work1);
}
if (timestep % d_visualization_interval == 0) {
// Write the vis files
auto work =
new IOWorkItem( timestep, input_db, d_meshData, Averages, d_n, d_rank_info, getComm() );
auto work = new IOWorkItem(timestep, input_db, d_meshData, Averages,
d_n, d_rank_info, getComm());
work->add_dependency(d_wait_analysis);
work->add_dependency(d_wait_subphase);
work->add_dependency(d_wait_vis);
@ -1275,9 +1228,9 @@ void runAnalysis::basic( int timestep, std::shared_ptr<Database> input_db, SubPh
}
void runAnalysis::WriteVisData(int timestep, std::shared_ptr<Database> input_db,
SubPhase &Averages, const double *Phi, double *Pressure, double *Velocity, double *fq,
double *Den )
{
SubPhase &Averages, const double *Phi,
double *Pressure, double *Velocity, double *fq,
double *Den) {
auto color_db = input_db->getDatabase("Color");
auto vis_db = input_db->getDatabase("Visualization");
// int timestep = color_db->getWithDefault<int>( "timestep", 0 );
@ -1299,8 +1252,8 @@ void runAnalysis::WriteVisData( int timestep, std::shared_ptr<Database> input_db
PROFILE_START("write vis", 1);
// if (Averages.WriteVis == true){
auto work2 =
new IOWorkItem( timestep, input_db, d_meshData, Averages, d_n, d_rank_info, getComm() );
auto work2 = new IOWorkItem(timestep, input_db, d_meshData, Averages, d_n,
d_rank_info, getComm());
work2->add_dependency(d_wait_vis);
d_wait_vis = d_tpool.add_work(work2);

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RunAnalysis_H_INC
#define RunAnalysis_H_INC
@ -10,7 +26,6 @@
#include "models/ColorModel.h"
#include <limits.h>
// Types of analysis
enum class AnalysisType : uint64_t {
AnalyzeNone = 0,
@ -23,15 +38,13 @@ enum class AnalysisType : uint64_t {
ComputeSubphase = 0x40
};
//! Class to run the analysis in multiple threads
class runAnalysis
{
class runAnalysis {
public:
//! Constructor
runAnalysis(std::shared_ptr<Database> db, const RankInfoStruct &rank_info,
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm, std::shared_ptr<Domain> dm, int Np,
bool Regular, IntArray Map );
std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm,
std::shared_ptr<Domain> dm, int Np, bool Regular, IntArray Map);
runAnalysis(ScaLBL_ColorModel &ColorModel);
@ -39,13 +52,16 @@ public:
~runAnalysis();
//! Run the next analysis
void run( int timestep, std::shared_ptr<Database> db, TwoPhase &Averages, const double *Phi,
double *Pressure, double *Velocity, double *fq, double *Den );
void run(int timestep, std::shared_ptr<Database> db, TwoPhase &Averages,
const double *Phi, double *Pressure, double *Velocity, double *fq,
double *Den);
void basic( int timestep, std::shared_ptr<Database> db, SubPhase &Averages, const double *Phi,
double *Pressure, double *Velocity, double *fq, double *Den );
void WriteVisData( int timestep, std::shared_ptr<Database> vis_db, SubPhase &Averages,
const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den );
void basic(int timestep, std::shared_ptr<Database> db, SubPhase &Averages,
const double *Phi, double *Pressure, double *Velocity,
double *fq, double *Den);
void WriteVisData(int timestep, std::shared_ptr<Database> vis_db,
SubPhase &Averages, const double *Phi, double *Pressure,
double *Velocity, double *fq, double *Den);
//! Finish all active analysis
void finish();
@ -64,8 +80,8 @@ public:
* that all threads run on independent cores
* @param[in] N_threads Number of threads, only used by some of the methods
*/
void createThreads( const std::string &method = "default", int N_threads = 4 );
void createThreads(const std::string &method = "default",
int N_threads = 4);
private:
runAnalysis();
@ -74,8 +90,7 @@ private:
AnalysisType computeAnalysisType(int timestep);
public:
class commWrapper
{
class commWrapper {
public:
Utilities::MPI comm;
int tag;
@ -96,10 +111,13 @@ private:
std::array<int, 3> d_N; // Number of local cells with ghosts
int d_Np;
int d_rank;
int d_restart_interval, d_analysis_interval, d_blobid_interval, d_visualization_interval;
int d_restart_interval, d_analysis_interval, d_blobid_interval,
d_visualization_interval;
int d_subphase_analysis_interval;
double d_beta;
bool d_regular;
std::string format; // IO format string "silo" or "hdf5"
ThreadPool d_tpool;
RankInfoStruct d_rank_info;
IntArray d_Map;

View File

@ -1,22 +1,34 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "analysis/uCT.h"
#include "analysis/analysis.h"
#include "analysis/distance.h"
#include "analysis/filters.h"
#include "analysis/imfilter.h"
template<class T>
inline int sign( T x )
{
template <class T> inline int sign(T x) {
if (x == 0)
return 0;
return x > 0 ? 1 : -1;
}
inline float trilinear(float dx, float dy, float dz, float f1, float f2,
float f3, float f4, float f5, float f6, float f7, float f8 )
{
float f3, float f4, float f5, float f6, float f7,
float f8) {
double f, dx2, dy2, dz2, h0, h1;
dx2 = 1.0 - dx;
dy2 = 1.0 - dy;
@ -27,9 +39,7 @@ inline float trilinear( float dx, float dy, float dz, float f1, float f2,
return (f);
}
void InterpolateMesh( const Array<float> &Coarse, Array<float> &Fine )
{
void InterpolateMesh(const Array<float> &Coarse, Array<float> &Fine) {
PROFILE_START("InterpolateMesh");
// Interpolate values from a Coarse mesh to a fine one
@ -79,9 +89,10 @@ void InterpolateMesh( const Array<float> &Coarse, Array<float> &Fine )
int i2 = i0 + 2;
float dx = ((i + 0.5) - (i0 + 0.5) * hx) / hx;
ASSERT(i0 >= -1 && i0 < nx + 1 && dx >= 0 && dx <= 1);
float val = trilinear( dx, dy, dz,
Coarse(i1,j1,k1), Coarse(i2,j1,k1), Coarse(i1,j2,k1), Coarse(i2,j2,k1),
Coarse(i1,j1,k2), Coarse(i2,j1,k2), Coarse(i1,j2,k2), Coarse(i2,j2,k2) );
float val = trilinear(
dx, dy, dz, Coarse(i1, j1, k1), Coarse(i2, j1, k1),
Coarse(i1, j2, k1), Coarse(i2, j2, k1), Coarse(i1, j1, k2),
Coarse(i2, j1, k2), Coarse(i1, j2, k2), Coarse(i2, j2, k2));
Fine(i + 1, j + 1, k + 1) = mapvalue * val;
}
}
@ -89,10 +100,9 @@ void InterpolateMesh( const Array<float> &Coarse, Array<float> &Fine )
PROFILE_STOP("InterpolateMesh");
}
// Smooth the data using the distance
void smooth( const Array<float>& VOL, const Array<float>& Dist, float sigma, Array<float>& MultiScaleSmooth, fillHalo<float>& fillFloat )
{
void smooth(const Array<float> &VOL, const Array<float> &Dist, float sigma,
Array<float> &MultiScaleSmooth, fillHalo<float> &fillFloat) {
for (size_t i = 0; i < VOL.length(); i++) {
// use exponential weight based on the distance
float dst = Dist(i);
@ -103,10 +113,8 @@ void smooth( const Array<float>& VOL, const Array<float>& Dist, float sigma, Arr
fillFloat.fill(MultiScaleSmooth);
}
// Segment the data
void segment( const Array<float>& data, Array<char>& ID, float tol )
{
void segment(const Array<float> &data, Array<char> &ID, float tol) {
ASSERT(data.size() == ID.size());
for (size_t i = 0; i < data.length(); i++) {
if (data(i) > tol)
@ -116,10 +124,8 @@ void segment( const Array<float>& data, Array<char>& ID, float tol )
}
}
// Remove disconnected phases
void removeDisconnected( Array<char>& ID, const Domain& Dm )
{
void removeDisconnected(Array<char> &ID, const Domain &Dm) {
// Run blob identification to remove disconnected volumes
BlobIDArray GlobalBlobID;
DoubleArray SignDist(ID.size());
@ -129,7 +135,8 @@ void removeDisconnected( Array<char>& ID, const Domain& Dm )
Phase(i) = 1;
}
ComputeGlobalBlobIDs(ID.size(0) - 2, ID.size(1) - 2, ID.size(2) - 2,
Dm.rank_info, Phase, SignDist, 0, 0, GlobalBlobID, Dm.Comm );
Dm.rank_info, Phase, SignDist, 0, 0, GlobalBlobID,
Dm.Comm);
for (size_t i = 0; i < ID.length(); i++) {
if (GlobalBlobID(i) > 0)
ID(i) = 0;
@ -137,13 +144,12 @@ void removeDisconnected( Array<char>& ID, const Domain& Dm )
}
}
// Solve a level (without any coarse level information)
void solve(const Array<float> &VOL, Array<float> &Mean, Array<char> &ID,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean,
fillHalo<float>& fillFloat, const Domain& Dm, int nprocx,
float threshold, float lamda, float sigsq, int depth)
{
Array<float> &Dist, Array<float> &MultiScaleSmooth,
Array<float> &NonLocalMean, fillHalo<float> &fillFloat,
const Domain &Dm, int nprocx, float threshold, float lamda,
float sigsq, int depth) {
PROFILE_SCOPED(timer, "solve");
// Compute the median filter on the sparse array
Med3D(VOL, Mean);
@ -156,19 +162,18 @@ void solve( const Array<float>& VOL, Array<float>& Mean, Array<char>& ID,
// Compute non-local mean
// int depth = 5;
// float sigsq=0.1;
int nlm_count = NLM3D( MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq);
int nlm_count =
NLM3D(MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq);
NULL_USE(nlm_count);
fillFloat.fill(NonLocalMean);
}
// Refine a solution from a coarse grid to a fine grid
void refine( const Array<float>& Dist_coarse,
const Array<float>& VOL, Array<float>& Mean, Array<char>& ID,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean,
void refine(const Array<float> &Dist_coarse, const Array<float> &VOL,
Array<float> &Mean, Array<char> &ID, Array<float> &Dist,
Array<float> &MultiScaleSmooth, Array<float> &NonLocalMean,
fillHalo<float> &fillFloat, const Domain &Dm, int nprocx, int level,
float threshold, float lamda, float sigsq, int depth)
{
float threshold, float lamda, float sigsq, int depth) {
PROFILE_SCOPED(timer, "refine");
int ratio[3] = {int(Dist.size(0) / Dist_coarse.size(0)),
int(Dist.size(1) / Dist_coarse.size(1)),
@ -186,22 +191,26 @@ void refine( const Array<float>& Dist_coarse,
Dist(i) = 0;
}
fillFloat.fill(Dist);
std::function<float(int,const float*)> filter_1D = []( int N, const float* data )
{
std::function<float(int, const float *)> filter_1D = [](int N,
const float *data) {
bool zero = data[0] == 0 || data[2] == 0;
return zero ? data[1] * 1e-12 : data[1];
};
std::vector<imfilter::BC> BC(3, imfilter::BC::replicate);
std::vector<std::function<float(int,const float*)>> filter_set(3,filter_1D);
std::vector<std::function<float(int, const float *)>> filter_set(3,
filter_1D);
Dist = imfilter::imfilter_separable<float>(Dist, {1, 1, 1}, filter_set, BC);
fillFloat.fill(Dist);
// Smooth the volume data
float h = 2*lamda*sqrt(double(ratio[0]*ratio[0]+ratio[1]*ratio[1]+ratio[2]*ratio[2]));
float h = 2 * lamda *
sqrt(double(ratio[0] * ratio[0] + ratio[1] * ratio[1] +
ratio[2] * ratio[2]));
smooth(VOL, Dist, h, MultiScaleSmooth, fillFloat);
// Compute non-local mean
// int depth = 3;
// float sigsq = 0.1;
int nlm_count = NLM3D( MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq);
int nlm_count =
NLM3D(MultiScaleSmooth, Mean, Dist, NonLocalMean, depth, sigsq);
NULL_USE(nlm_count);
fillFloat.fill(NonLocalMean);
segment(NonLocalMean, ID, 0.001);
@ -219,14 +228,13 @@ void refine( const Array<float>& Dist_coarse,
}
}
// Remove regions that are likely noise by shrinking the volumes by dx,
// removing all values that are more than dx+delta from the surface, and then
// growing by dx+delta and intersecting with the original data
void filter_final(Array<char> &ID, Array<float> &Dist,
fillHalo<float> &fillFloat, const Domain &Dm,
Array<float>& Mean, Array<float>& Dist1, Array<float>& Dist2 )
{
Array<float> &Mean, Array<float> &Dist1,
Array<float> &Dist2) {
PROFILE_SCOPED(timer, "filter_final");
int rank = Dm.Comm.getRank();
int Nx = Dm.Nx - 2;
@ -241,7 +249,8 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
float tmp = 0;
for (size_t i = 0; i < Dist0.length(); i++)
tmp += Dist0(i) * Dist0(i);
tmp = sqrt( Dm.Comm.sumReduce(tmp) / Dm.Comm.sumReduce<float>(Dist0.length()) );
tmp =
sqrt(Dm.Comm.sumReduce(tmp) / Dm.Comm.sumReduce<float>(Dist0.length()));
const float dx1 = 0.3 * tmp;
const float dx2 = 1.05 * dx1;
if (rank == 0)
@ -273,8 +282,10 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
}
}
// Find regions of uncertainty that are entirely contained within another region
fillHalo<double> fillDouble(Dm.Comm,Dm.rank_info,{Nx,Ny,Nz},{1,1,1},0,1);
fillHalo<BlobIDType> fillInt(Dm.Comm,Dm.rank_info,{Nx,Ny,Nz},{1,1,1},0,1);
fillHalo<double> fillDouble(Dm.Comm, Dm.rank_info, {Nx, Ny, Nz}, {1, 1, 1},
0, 1);
fillHalo<BlobIDType> fillInt(Dm.Comm, Dm.rank_info, {Nx, Ny, Nz}, {1, 1, 1},
0, 1);
BlobIDArray GlobalBlobID;
DoubleArray SignDist(ID.size());
for (size_t i = 0; i < ID.length(); i++)
@ -282,7 +293,8 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
fillDouble.fill(SignDist);
DoubleArray Phase(ID.size());
Phase.fill(1);
ComputeGlobalBlobIDs( Nx, Ny, Nz, Dm.rank_info, Phase, SignDist, 0, 0, GlobalBlobID, Dm.Comm );
ComputeGlobalBlobIDs(Nx, Ny, Nz, Dm.rank_info, Phase, SignDist, 0, 0,
GlobalBlobID, Dm.Comm);
fillInt.fill(GlobalBlobID);
int N_blobs = Dm.Comm.maxReduce(GlobalBlobID.max() + 1);
std::vector<float> mean(N_blobs, 0);
@ -348,20 +360,20 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
fillFloat.fill(Dist);
}
// Filter the original data
void filter_src( const Domain& Dm, Array<float>& src )
{
void filter_src(const Domain &Dm, Array<float> &src) {
PROFILE_START("Filter source data");
int Nx = Dm.Nx - 2;
int Ny = Dm.Ny - 2;
int Nz = Dm.Nz - 2;
fillHalo<float> fillFloat(Dm.Comm,Dm.rank_info,{Nx,Ny,Nz},{1,1,1},0,1);
fillHalo<float> fillFloat(Dm.Comm, Dm.rank_info, {Nx, Ny, Nz}, {1, 1, 1}, 0,
1);
// Perform a hot-spot filter on the data
std::vector<imfilter::BC> BC = { imfilter::BC::replicate, imfilter::BC::replicate, imfilter::BC::replicate };
std::function<float(const Array<float>&)> filter_3D = []( const Array<float>& data )
{
std::vector<imfilter::BC> BC = {imfilter::BC::replicate,
imfilter::BC::replicate,
imfilter::BC::replicate};
std::function<float(const Array<float> &)> filter_3D =
[](const Array<float> &data) {
float min1 = std::min(data(0, 1, 1), data(2, 1, 1));
float min2 = std::min(data(1, 0, 1), data(1, 2, 1));
float min3 = std::min(data(1, 1, 0), data(1, 1, 2));
@ -372,14 +384,15 @@ void filter_src( const Domain& Dm, Array<float>& src )
float max = std::max(max1, std::max(max2, max3));
return std::max(std::min(data(1, 1, 1), max), min);
};
std::function<float(const Array<float>&)> filter_1D = []( const Array<float>& data )
{
std::function<float(const Array<float> &)> filter_1D =
[](const Array<float> &data) {
float min = std::min(data(0), data(2));
float max = std::max(data(0), data(2));
return std::max(std::min(data(1), max), min);
};
//LOCVOL[0] = imfilter::imfilter<float>( LOCVOL[0], {1,1,1}, filter_3D, BC );
std::vector<std::function<float(const Array<float>&)>> filter_set(3,filter_1D);
std::vector<std::function<float(const Array<float> &)>> filter_set(
3, filter_1D);
src = imfilter::imfilter_separable<float>(src, {1, 1, 1}, filter_set, BC);
fillFloat.fill(src);
// Perform a gaussian filter on the data

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef uCT_H_INC
#define uCT_H_INC
@ -5,8 +21,6 @@
#include "common/Domain.h"
#include "common/Communication.h"
/*!
* @brief Interpolate between meshes
* @details This routine interpolates from a coarse to a fine mesh
@ -15,34 +29,30 @@
*/
void InterpolateMesh(const Array<float> &Coarse, Array<float> &Fine);
// Smooth the data using the distance
void smooth( const Array<float>& VOL, const Array<float>& Dist, float sigma, Array<float>& MultiScaleSmooth, fillHalo<float>& fillFloat );
void smooth(const Array<float> &VOL, const Array<float> &Dist, float sigma,
Array<float> &MultiScaleSmooth, fillHalo<float> &fillFloat);
// Segment the data
void segment(const Array<float> &data, Array<char> &ID, float tol);
// Remove disconnected phases
void removeDisconnected(Array<char> &ID, const Domain &Dm);
// Solve a level (without any coarse level information)
void solve(const Array<float> &VOL, Array<float> &Mean, Array<char> &ID,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean,
fillHalo<float>& fillFloat, const Domain& Dm, int nprocx,
float threshold, float lamda, float sigsq, int depth);
Array<float> &Dist, Array<float> &MultiScaleSmooth,
Array<float> &NonLocalMean, fillHalo<float> &fillFloat,
const Domain &Dm, int nprocx, float threshold, float lamda,
float sigsq, int depth);
// Refine a solution from a coarse grid to a fine grid
void refine( const Array<float>& Dist_coarse,
const Array<float>& VOL, Array<float>& Mean, Array<char>& ID,
Array<float>& Dist, Array<float>& MultiScaleSmooth, Array<float>& NonLocalMean,
void refine(const Array<float> &Dist_coarse, const Array<float> &VOL,
Array<float> &Mean, Array<char> &ID, Array<float> &Dist,
Array<float> &MultiScaleSmooth, Array<float> &NonLocalMean,
fillHalo<float> &fillFloat, const Domain &Dm, int nprocx, int level,
float threshold, float lamda, float sigsq, int depth);
// Remove regions that are likely noise by shrinking the volumes by dx,
// removing all values that are more than dx+delta from the surface, and then
// growing by dx+delta and intersecting with the original data
@ -50,9 +60,7 @@ void filter_final( Array<char>& ID, Array<float>& Dist,
fillHalo<float> &fillFloat, const Domain &Dm,
Array<float> &Mean, Array<float> &Dist1, Array<float> &Dist2);
// Filter the original data
void filter_src(const Domain &Dm, Array<float> &src);
#endif

84
clang-format-all Executable file
View File

@ -0,0 +1,84 @@
#!/bin/bash
#
# clang-format-all: a tool to run clang-format on an entire project
# Copyright (C) 2016 Evan Klitzke <evan@eklitzke.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
function usage {
echo "Usage: $0 DIR..."
exit 1
}
if [ $# -eq 0 ]; then
usage
fi
# Variable that will hold the name of the clang-format command
FMT=""
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
# that the version number be part of the command. We prefer clang-format if
# that's present, otherwise we work backwards from highest version to lowest
# version.
for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
if which "$clangfmt" &>/dev/null; then
FMT="$clangfmt"
break
fi
done
# Check if we found a working clang-format
if [ -z "$FMT" ]; then
echo "failed to find clang-format"
exit 1
fi
# Check all of the arguments first to make sure they're all directories
for dir in "$@"; do
if [ ! -d "${dir}" ]; then
echo "${dir} is not a directory"
usage
fi
done
# Find a dominating file, starting from a given directory and going up.
find-dominating-file() {
if [ -r "$1"/"$2" ]; then
return 0
fi
if [ "$1" = "/" ]; then
return 1
fi
find-dominating-file "$(realpath "$1"/..)" "$2"
return $?
}
# Run clang-format -i on all of the things
for dir in "$@"; do
pushd "${dir}" &>/dev/null
if ! find-dominating-file . .clang-format; then
echo "Failed to find dominating .clang-format starting at $PWD"
continue
fi
find . \
\( -name '*.c' \
-o -name '*.cc' \
-o -name '*.cpp' \
-o -name '*.h' \
-o -name '*.hh' \
-o -name '*.hpp' \) \
-exec "${FMT}" -i '{}' \;
popd &>/dev/null
done

View File

@ -263,7 +263,7 @@ ENDMACRO ()
# Macro to configure LBPM specific options
MACRO ( CONFIGURE_LBPM )
# Set the maximum number of processors for the tests
IF ( NOT TEST_MAX_PROCS )
IF ( NOT DEFINED TEST_MAX_PROCS )
SET( TEST_MAX_PROCS 32 )
ENDIF()
# Add the correct paths to rpath in case we build shared libraries

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_ArrayClass
#define included_ArrayClass
@ -13,13 +29,10 @@
#include <string>
#include <vector>
/*!
* Class Array is a multi-dimensional array class written by Mark Berrill
*/
template<class TYPE, class FUN, class Allocator>
class Array final
{
template <class TYPE, class FUN, class Allocator> class Array final {
public: // Constructors / assignment operators
/*!
* Create a new empty Array
@ -97,7 +110,6 @@ public: // Constructors / assignment operators
*/
Array(std::initializer_list<std::initializer_list<TYPE>> data);
/*!
* Copy constructor
* @param rhs Array to copy
@ -140,24 +152,22 @@ public: // Constructors / assignment operators
//! Set is copyable
inline void setFixedSize(bool flag) { d_isFixedSize = flag; }
public: // Views/copies/subset
/*!
* Create a multi-dimensional Array view to a raw block of data
* @param N Number of elements in each dimension
* @param data Pointer to the data
*/
static std::unique_ptr<Array> view( const ArraySize &N, std::shared_ptr<TYPE> data );
static std::unique_ptr<Array> view(const ArraySize &N,
std::shared_ptr<TYPE> data);
/*!
* Create a multi-dimensional Array view to a raw block of data
* @param N Number of elements in each dimension
* @param data Pointer to the data
*/
static std::unique_ptr<const Array> constView( const ArraySize &N,
std::shared_ptr<const TYPE> const &data );
static std::unique_ptr<const Array>
constView(const ArraySize &N, std::shared_ptr<const TYPE> const &data);
/*!
* Make this object a view of the src
@ -185,9 +195,8 @@ public: // Views/copies/subset
* @param isCopyable Once the view is created, can the array be copied
* @param isFixedSize Once the view is created, is the array size fixed
*/
inline void viewRaw(
int ndim, const size_t *dims, TYPE *data, bool isCopyable = true, bool isFixedSize = true )
{
inline void viewRaw(int ndim, const size_t *dims, TYPE *data,
bool isCopyable = true, bool isFixedSize = true) {
viewRaw(ArraySize(ndim, dims), data, isCopyable, isFixedSize);
}
@ -203,7 +212,8 @@ public: // Views/copies/subset
* @param isCopyable Once the view is created, can the array be copied
* @param isFixedSize Once the view is created, is the array size fixed
*/
void viewRaw( const ArraySize &N, TYPE *data, bool isCopyable = true, bool isFixedSize = true );
void viewRaw(const ArraySize &N, TYPE *data, bool isCopyable = true,
bool isFixedSize = true);
/*!
* Create an array view of the given data (expert use only).
@ -215,8 +225,7 @@ public: // Views/copies/subset
* @param N Number of elements in each dimension
* @param data Pointer to the data
*/
static inline Array staticView( const ArraySize &N, TYPE *data )
{
static inline Array staticView(const ArraySize &N, TYPE *data) {
Array x;
x.viewRaw(N, data, true, true);
return x;
@ -228,35 +237,30 @@ public: // Views/copies/subset
*/
template <class TYPE2>
static inline std::unique_ptr<Array<TYPE2, FUN, Allocator>>
convert( std::shared_ptr<Array<TYPE, FUN, Allocator>> array )
{
convert(std::shared_ptr<Array<TYPE, FUN, Allocator>> array) {
auto array2 = std::make_unique<Array<TYPE2>>(array->size());
array2.copy(*array);
return array2;
}
/*!
* Convert an array of one type to another. This may or may not allocate new memory.
* @param array Input array
*/
template <class TYPE2>
static inline std::unique_ptr<const Array<TYPE2, FUN, Allocator>>
convert( std::shared_ptr<const Array<TYPE, FUN, Allocator>> array )
{
convert(std::shared_ptr<const Array<TYPE, FUN, Allocator>> array) {
auto array2 = std::make_unique<Array<TYPE2>>(array->size());
array2.copy(*array);
return array2;
}
/*!
* Copy and convert data from another array to this array
* @param array Source array
*/
template <class TYPE2, class FUN2, class Allocator2>
void inline copy( const Array<TYPE2, FUN2, Allocator2> &array )
{
void inline copy(const Array<TYPE2, FUN2, Allocator2> &array) {
resize(array.size());
copy(array.data());
}
@ -266,38 +270,32 @@ public: // Views/copies/subset
* Note: The current array must be allocated to the proper size first.
* @param data Source data
*/
template<class TYPE2>
inline void copy( const TYPE2 *data );
template <class TYPE2> inline void copy(const TYPE2 *data);
/*!
* Copy and convert data from this array to a raw vector.
* @param data Source data
*/
template<class TYPE2>
inline void copyTo( TYPE2 *data ) const;
template <class TYPE2> inline void copyTo(TYPE2 *data) const;
/*!
* Copy and convert data from this array to a new array
*/
template <class TYPE2>
Array<TYPE2, FUN, std::allocator<TYPE2>> inline cloneTo() const
{
Array<TYPE2, FUN, std::allocator<TYPE2>> inline cloneTo() const {
Array<TYPE2, FUN, std::allocator<TYPE2>> dst(this->size());
copyTo(dst.data());
return dst;
}
/*! swap the raw data pointers for the Arrays after checking for compatibility */
void swap(Array &other);
/*!
* Fill the array with the given value
* @param y Value to fill
*/
inline void fill( const TYPE &y )
{
inline void fill(const TYPE &y) {
for (auto &x : *this)
x = y;
}
@ -306,14 +304,11 @@ public: // Views/copies/subset
* Scale the array by the given value
* @param y Value to scale by
*/
template<class TYPE2>
inline void scale( const TYPE2 &y )
{
template <class TYPE2> inline void scale(const TYPE2 &y) {
for (auto &x : *this)
x *= y;
}
/*!
* Set the values of this array to pow(base, exp)
* @param base Base array
@ -321,52 +316,44 @@ public: // Views/copies/subset
*/
void pow(const Array &base, const TYPE &exp);
//! Destructor
~Array();
//! Clear the data in the array
void clear();
//! Return the size of the Array
inline int ndim() const { return d_size.ndim(); }
//! Return the size of the Array
inline const ArraySize &size() const { return d_size; }
//! Return the size of the Array
inline size_t size(int d) const { return d_size[d]; }
//! Return the size of the Array
inline size_t length() const { return d_size.length(); }
//! Return true if the Array is empty
inline bool empty() const { return d_size.length() == 0; }
//! Return true if the Array is not empty
inline operator bool() const { return d_size.length() != 0; }
/*!
* Resize the Array
* @param N NUmber of elements
*/
inline void resize(size_t N) { resize(ArraySize(N)); }
/*!
* Resize the Array
* @param N_row Number of rows
* @param N_col Number of columns
*/
inline void resize( size_t N_row, size_t N_col ) { resize( ArraySize( N_row, N_col ) ); }
inline void resize(size_t N_row, size_t N_col) {
resize(ArraySize(N_row, N_col));
}
/*!
* Resize the Array
@ -374,7 +361,9 @@ public: // Views/copies/subset
* @param N2 Number of columns
* @param N3 Number of elements in the third dimension
*/
inline void resize( size_t N1, size_t N2, size_t N3 ) { resize( ArraySize( N1, N2, N3 ) ); }
inline void resize(size_t N1, size_t N2, size_t N3) {
resize(ArraySize(N1, N2, N3));
}
/*!
* Resize the Array
@ -382,7 +371,6 @@ public: // Views/copies/subset
*/
void resize(const ArraySize &N);
/*!
* Resize the given dimension of the array
* @param dim The dimension to resize
@ -391,20 +379,17 @@ public: // Views/copies/subset
*/
void resizeDim(int dim, size_t N, const TYPE &value);
/*!
* Reshape the Array (total size of array will not change)
* @param N Number of elements in each dimension
*/
void reshape(const ArraySize &N);
/*!
* Remove singleton dimensions.
*/
void squeeze();
/*!
* Reshape the Array so that the number of dimensions is the
* max of ndim and the largest dim>1.
@ -412,21 +397,18 @@ public: // Views/copies/subset
*/
inline void setNdim(int ndim) { d_size.setNdim(ndim); }
/*!
* Subset the Array
* @param index Index to subset (imin,imax,jmin,jmax,kmin,kmax,...)
*/
Array subset(const std::vector<size_t> &index) const;
/*!
* Subset the Array
* @param index Index to subset (ix:kx:jx,iy:ky:jy,...)
*/
Array subset(const std::vector<Range<size_t>> &index) const;
/*!
* Copy data from an array into a subset of this array
* @param index Index of the subset (imin,imax,jmin,jmax,kmin,kmax,...)
@ -439,7 +421,8 @@ public: // Views/copies/subset
* @param index Index of the subset
* @param subset The subset array to copy from
*/
void copySubset( const std::vector<Range<size_t>> &index, const Array &subset );
void copySubset(const std::vector<Range<size_t>> &index,
const Array &subset);
/*!
* Add data from an array into a subset of this array
@ -453,22 +436,23 @@ public: // Views/copies/subset
* @param index Index of the subset
* @param subset The subset array to add from
*/
void addSubset( const std::vector<Range<size_t>> &index, const Array &subset );
void addSubset(const std::vector<Range<size_t>> &index,
const Array &subset);
public: // Accessors
/*!
* Access the desired element
* @param i The row index
*/
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i ) { return d_data[d_size.index( i )]; }
ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i) {
return d_data[d_size.index(i)];
}
/*!
* Access the desired element
* @param i The row index
*/
ARRAY_ATTRIBUTE inline const TYPE &operator()( size_t i ) const
{
ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i) const {
return d_data[d_size.index(i)];
}
@ -477,8 +461,7 @@ public: // Accessors
* @param i The row index
* @param j The column index
*/
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i, size_t j )
{
ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i, size_t j) {
return d_data[d_size.index(i, j)];
}
@ -487,8 +470,7 @@ public: // Accessors
* @param i The row index
* @param j The column index
*/
ARRAY_ATTRIBUTE inline const TYPE &operator()( size_t i, size_t j ) const
{
ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i, size_t j) const {
return d_data[d_size.index(i, j)];
}
@ -498,8 +480,7 @@ public: // Accessors
* @param j The column index
* @param k The third index
*/
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i, size_t j, size_t k )
{
ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i, size_t j, size_t k) {
return d_data[d_size.index(i, j, k)];
}
@ -509,8 +490,8 @@ public: // Accessors
* @param j The column index
* @param k The third index
*/
ARRAY_ATTRIBUTE inline const TYPE &operator()( size_t i, size_t j, size_t k ) const
{
ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i, size_t j,
size_t k) const {
return d_data[d_size.index(i, j, k)];
}
@ -521,8 +502,8 @@ public: // Accessors
* @param i3 The third index
* @param i4 The fourth index
*/
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i1, size_t i2, size_t i3, size_t i4 )
{
ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i1, size_t i2, size_t i3,
size_t i4) {
return d_data[d_size.index(i1, i2, i3, i4)];
}
@ -533,9 +514,8 @@ public: // Accessors
* @param i3 The third index
* @param i4 The fourth index
*/
ARRAY_ATTRIBUTE inline const TYPE &
operator()( size_t i1, size_t i2, size_t i3, size_t i4 ) const
{
ARRAY_ATTRIBUTE inline const TYPE &operator()(size_t i1, size_t i2,
size_t i3, size_t i4) const {
return d_data[d_size.index(i1, i2, i3, i4)];
}
@ -547,8 +527,8 @@ public: // Accessors
* @param i4 The fourth index
* @param i5 The fifth index
*/
ARRAY_ATTRIBUTE inline TYPE &operator()( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 )
{
ARRAY_ATTRIBUTE inline TYPE &operator()(size_t i1, size_t i2, size_t i3,
size_t i4, size_t i5) {
return d_data[d_size.index(i1, i2, i3, i4, i5)];
}
@ -561,8 +541,7 @@ public: // Accessors
* @param i5 The fifth index
*/
ARRAY_ATTRIBUTE inline const TYPE &
operator()( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 ) const
{
operator()(size_t i1, size_t i2, size_t i3, size_t i4, size_t i5) const {
return d_data[d_size.index(i1, i2, i3, i4, i5)];
}
@ -570,8 +549,7 @@ public: // Accessors
* Access the desired element as a raw pointer
* @param i The global index
*/
ARRAY_ATTRIBUTE inline TYPE *ptr( size_t i )
{
ARRAY_ATTRIBUTE inline TYPE *ptr(size_t i) {
return i >= d_size.length() ? nullptr : &d_data[i];
}
@ -579,8 +557,7 @@ public: // Accessors
* Access the desired element as a raw pointer
* @param i The global index
*/
ARRAY_ATTRIBUTE inline const TYPE *ptr( size_t i ) const
{
ARRAY_ATTRIBUTE inline const TYPE *ptr(size_t i) const {
return i >= d_size.length() ? nullptr : &d_data[i];
}
@ -608,14 +585,15 @@ public: // Accessors
//! Return the pointer to the raw data
ARRAY_ATTRIBUTE inline const TYPE *data() const { return d_data; }
public: // Operator overloading
//! Check if two matrices are equal
// Equality means the dimensions and data have to be identical
bool operator==(const Array &rhs) const;
//! Check if two matrices are not equal
inline bool operator!=( const Array &rhs ) const { return !this->operator==( rhs ); }
inline bool operator!=(const Array &rhs) const {
return !this->operator==(rhs);
}
//! Add another array
Array &operator+=(const Array &rhs);
@ -629,7 +607,6 @@ public: // Operator overloading
//! Subtract a scalar
Array &operator-=(const TYPE &rhs);
public: // Math operations
//! Concatenates the arrays along the dimension dim.
static Array cat(const std::vector<Array> &x, int dim = 0);
@ -695,13 +672,13 @@ public: // Math operations
TYPE mean(const std::vector<Range<size_t>> &index) const;
//! Find all elements that match the operator
std::vector<size_t> find( const TYPE &value,
std::vector<size_t>
find(const TYPE &value,
std::function<bool(const TYPE &, const TYPE &)> compare) const;
//! Print an array
void
print( std::ostream &os, const std::string &name = "A", const std::string &prefix = "" ) const;
void print(std::ostream &os, const std::string &name = "A",
const std::string &prefix = "") const;
//! Transpose an array
Array reverseDim() const;
@ -741,7 +718,8 @@ public: // Math operations
* @param[in] fun The function operation
* @param[in] x The input array
*/
static Array transform( std::function<TYPE( const TYPE & )> fun, const Array &x );
static Array transform(std::function<TYPE(const TYPE &)> fun,
const Array &x);
/*!
* Perform a element-wise operation z = f(x,y)
@ -750,8 +728,7 @@ public: // Math operations
* @param[in] y The second array
*/
static Array transform(std::function<TYPE(const TYPE &, const TYPE &)> fun,
const Array &x,
const Array &y );
const Array &x, const Array &y);
/*!
* axpby operation: this = alpha*x + beta*this
@ -765,7 +742,9 @@ public: // Math operations
* Linear interpolation
* @param[in] x Position as a decimal index
*/
inline TYPE interp( const std::vector<double> &x ) const { return interp( x.data() ); }
inline TYPE interp(const std::vector<double> &x) const {
return interp(x.data());
}
/*!
* Linear interpolation
@ -792,7 +771,8 @@ private:
private:
inline void checkSubsetIndex(const std::vector<Range<size_t>> &range) const;
inline std::vector<Range<size_t>> convert( const std::vector<size_t> &index ) const;
inline std::vector<Range<size_t>>
convert(const std::vector<size_t> &index) const;
static inline void getSubsetArrays(const std::vector<Range<size_t>> &range,
std::array<size_t, 5> &first,
std::array<size_t, 5> &last,
@ -800,12 +780,10 @@ private:
std::array<size_t, 5> &N);
};
/********************************************************
* ostream operator *
********************************************************/
inline std::ostream &operator<<( std::ostream &out, const ArraySize &s )
{
inline std::ostream &operator<<(std::ostream &out, const ArraySize &s) {
out << "[" << s[0];
for (size_t i = 1; i < s.ndim(); i++)
out << "," << s[i];
@ -813,70 +791,64 @@ inline std::ostream &operator<<( std::ostream &out, const ArraySize &s )
return out;
}
/********************************************************
* Math operations *
********************************************************/
template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator+(
const Array<TYPE, FUN, Allocator> &a, const Array<TYPE, FUN, Allocator> &b )
{
inline Array<TYPE, FUN, Allocator>
operator+(const Array<TYPE, FUN, Allocator> &a,
const Array<TYPE, FUN, Allocator> &b) {
Array<TYPE, FUN, Allocator> c;
const auto &op = [](const TYPE &a, const TYPE &b) { return a + b; };
FUN::transform(op, a, b, c);
return c;
}
template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator-(
const Array<TYPE, FUN, Allocator> &a, const Array<TYPE, FUN, Allocator> &b )
{
inline Array<TYPE, FUN, Allocator>
operator-(const Array<TYPE, FUN, Allocator> &a,
const Array<TYPE, FUN, Allocator> &b) {
Array<TYPE, FUN, Allocator> c;
const auto &op = [](const TYPE &a, const TYPE &b) { return a - b; };
FUN::transform(op, a, b, c);
return c;
}
template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*(
const Array<TYPE, FUN, Allocator> &a, const Array<TYPE, FUN, Allocator> &b )
{
inline Array<TYPE, FUN, Allocator>
operator*(const Array<TYPE, FUN, Allocator> &a,
const Array<TYPE, FUN, Allocator> &b) {
Array<TYPE, FUN, Allocator> c;
FUN::multiply(a, b, c);
return c;
}
template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*(
const Array<TYPE, FUN, Allocator> &a, const std::vector<TYPE> &b )
{
inline Array<TYPE, FUN, Allocator>
operator*(const Array<TYPE, FUN, Allocator> &a, const std::vector<TYPE> &b) {
Array<TYPE, FUN, Allocator> b2, c;
b2.viewRaw({b.size()}, const_cast<TYPE *>(b.data()));
FUN::multiply(a, b2, c);
return c;
}
template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*( const TYPE &a,
const Array<TYPE, FUN, Allocator> &b )
{
inline Array<TYPE, FUN, Allocator>
operator*(const TYPE &a, const Array<TYPE, FUN, Allocator> &b) {
auto c = b;
c.scale(a);
return c;
}
template <class TYPE, class FUN, class Allocator>
inline Array<TYPE, FUN, Allocator> operator*( const Array<TYPE, FUN, Allocator> &a,
const TYPE &b )
{
inline Array<TYPE, FUN, Allocator>
operator*(const Array<TYPE, FUN, Allocator> &a, const TYPE &b) {
auto c = a;
c.scale(b);
return c;
}
/********************************************************
* Copy array *
********************************************************/
template <class TYPE, class FUN, class Allocator>
template <class TYPE2>
inline void Array<TYPE, FUN, Allocator>::copy( const TYPE2 *data )
{
inline void Array<TYPE, FUN, Allocator>::copy(const TYPE2 *data) {
if (std::is_same<TYPE, TYPE2>::value) {
std::copy(data, data + d_size.length(), d_data);
} else {
@ -886,8 +858,7 @@ inline void Array<TYPE, FUN, Allocator>::copy( const TYPE2 *data )
}
template <class TYPE, class FUN, class Allocator>
template <class TYPE2>
inline void Array<TYPE, FUN, Allocator>::copyTo( TYPE2 *data ) const
{
inline void Array<TYPE, FUN, Allocator>::copyTo(TYPE2 *data) const {
if (std::is_same<TYPE, TYPE2>::value) {
std::copy(d_data, d_data + d_size.length(), data);
} else {
@ -896,7 +867,6 @@ inline void Array<TYPE, FUN, Allocator>::copyTo( TYPE2 *data ) const
}
}
/********************************************************
* Convience typedefs *
* Copy array *
@ -904,5 +874,4 @@ inline void Array<TYPE, FUN, Allocator>::copyTo( TYPE2 *data ) const
typedef Array<double> DoubleArray;
typedef Array<int> IntArray;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@
#include <stdexcept>
#include <vector>
#if defined(__CUDA_ARCH__)
#include <cuda.h>
#define HOST_DEVICE __host__ __device__
@ -26,7 +25,6 @@
#define ARRAY_ATTRIBUTE HOST_DEVICE
#endif
#if (defined(DEBUG) || defined(_DEBUG)) && !defined(NDEBUG)
#define CHECK_ARRAY_LENGTH(i, length) \
do { \
@ -39,18 +37,14 @@
} while (0)
#endif
// Forward declerations
class FunctionTable;
template<class TYPE, class FUN = FunctionTable, class Allocator = std::allocator<TYPE>>
template <class TYPE, class FUN = FunctionTable,
class Allocator = std::allocator<TYPE>>
class Array;
//! Simple range class
template<class TYPE = size_t>
class Range final
{
template <class TYPE = size_t> class Range final {
public:
//! Empty constructor
Range() : i(0), j(-1), k(1) {}
@ -62,13 +56,10 @@ public:
* @param k_ Increment value
*/
Range(const TYPE &i_, const TYPE &j_, const TYPE &k_ = 1)
: i( i_ ), j( j_ ), k( k_ )
{
}
: i(i_), j(j_), k(k_) {}
//! Get the number of values in the range
size_t size() const
{
size_t size() const {
if (std::is_integral<TYPE>::value) {
return (static_cast<int64_t>(j) - static_cast<int64_t>(i)) /
static_cast<int64_t>(k);
@ -88,10 +79,8 @@ public:
TYPE i, j, k;
};
//! Simple class to store the array dimensions
class ArraySize final
{
class ArraySize final {
public:
//! Empty constructor
ArraySize() : d_ndim(1), d_length(0), d_N{0, 1, 1, 1, 1} {}
@ -108,9 +97,7 @@ public:
* @param N2 Number of elements in the second dimension
*/
ArraySize(size_t N1, size_t N2)
: d_ndim( 2 ), d_length( N1 * N2 ), d_N{ N1, N2, 1, 1, 1 }
{
}
: d_ndim(2), d_length(N1 * N2), d_N{N1, N2, 1, 1, 1} {}
/*!
* Create the vector size
@ -119,9 +106,7 @@ public:
* @param N3 Number of elements in the third dimension
*/
ArraySize(size_t N1, size_t N2, size_t N3)
: d_ndim( 3 ), d_length( N1 * N2 * N3 ), d_N{ N1, N2, N3, 1, 1 }
{
}
: d_ndim(3), d_length(N1 * N2 * N3), d_N{N1, N2, N3, 1, 1} {}
/*!
* Create the vector size
@ -131,9 +116,7 @@ public:
* @param N4 Number of elements in the fourth dimension
*/
ArraySize(size_t N1, size_t N2, size_t N3, size_t N4)
: d_ndim( 4 ), d_length( N1 * N2 * N3 * N4 ), d_N{ N1, N2, N3, N4, 1 }
{
}
: d_ndim(4), d_length(N1 * N2 * N3 * N4), d_N{N1, N2, N3, N4, 1} {}
/*!
* Create the vector size
@ -144,8 +127,7 @@ public:
* @param N5 Number of elements in the fifth dimension
*/
ArraySize(size_t N1, size_t N2, size_t N3, size_t N4, size_t N5)
: d_ndim( 5 ), d_length( N1 * N2 * N3 * N4 * N5 ), d_N{ N1, N2, N3, N4, N5 }
{
: d_ndim(5), d_length(N1 * N2 * N3 * N4 * N5), d_N{N1, N2, N3, N4, N5} {
}
/*!
@ -154,8 +136,7 @@ public:
* @param ndim Number of dimensions
*/
ArraySize(std::initializer_list<size_t> N, int ndim = -1)
: d_ndim( N.size() ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 }
{
: d_ndim(N.size()), d_length(0), d_N{0, 1, 1, 1, 1} {
if (ndim >= 0)
d_ndim = ndim;
if (d_ndim > 5)
@ -170,15 +151,13 @@ public:
d_length = 0;
}
/*!
* Create from raw pointer
* @param ndim Number of dimensions
* @param dims Dimensions
*/
ArraySize(size_t ndim, const size_t *dims)
: d_ndim( ndim ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 }
{
: d_ndim(ndim), d_length(0), d_N{0, 1, 1, 1, 1} {
if (d_ndim > 5)
throw std::out_of_range("Maximum number of dimensions exceeded");
for (size_t i = 0; i < ndim; i++)
@ -195,15 +174,14 @@ public:
* @param N Size of the array
*/
template <std::size_t NDIM>
ArraySize( const std::array<size_t, NDIM> &N ) : ArraySize( NDIM, N.data() )
{
}
ArraySize(const std::array<size_t, NDIM> &N) : ArraySize(NDIM, N.data()) {}
/*!
* Create from std::vector
* @param N Size of the array
*/
inline ArraySize( const std::vector<size_t> &N ) : ArraySize( N.size(), N.data() ) {}
inline ArraySize(const std::vector<size_t> &N)
: ArraySize(N.size(), N.data()) {}
// Copy/assignment constructors
ArraySize(ArraySize &&rhs) = default;
@ -227,8 +205,7 @@ public:
ARRAY_ATTRIBUTE size_t length() const { return d_length; }
//! Resize the dimension
void resize( uint8_t dim, size_t N )
{
void resize(uint8_t dim, size_t N) {
if (dim >= d_ndim)
throw std::out_of_range("Invalid dimension");
d_N[dim] = N;
@ -247,8 +224,7 @@ public:
/*!
* Remove singleton dimensions
*/
void squeeze()
{
void squeeze() {
d_ndim = 0;
for (uint8_t i = 0; i < maxDim(); i++) {
if (d_N[i] != 1)
@ -263,20 +239,18 @@ public:
const size_t *end() const { return d_N + d_ndim; }
// Check if two array sizes are equal
ARRAY_ATTRIBUTE bool operator==( const ArraySize &rhs ) const
{
ARRAY_ATTRIBUTE bool operator==(const ArraySize &rhs) const {
return d_ndim == rhs.d_ndim && memcmp(d_N, rhs.d_N, sizeof(d_N)) == 0;
}
// Check if two array sizes are equal (ignoring the dimension)
ARRAY_ATTRIBUTE bool approxEqual( const ArraySize &rhs ) const
{
return ( length() == 0 && rhs.length() == 0 ) || memcmp( d_N, rhs.d_N, sizeof( d_N ) ) == 0;
ARRAY_ATTRIBUTE bool approxEqual(const ArraySize &rhs) const {
return (length() == 0 && rhs.length() == 0) ||
memcmp(d_N, rhs.d_N, sizeof(d_N)) == 0;
}
//! Check if two matrices are not equal
ARRAY_ATTRIBUTE bool operator!=( const ArraySize &rhs ) const
{
ARRAY_ATTRIBUTE bool operator!=(const ArraySize &rhs) const {
return d_ndim != rhs.d_ndim || memcmp(d_N, rhs.d_N, sizeof(d_N)) != 0;
}
@ -284,48 +258,44 @@ public:
ARRAY_ATTRIBUTE static uint8_t maxDim() { return 5; }
//! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i ) const
{
ARRAY_ATTRIBUTE size_t index(size_t i) const {
CHECK_ARRAY_LENGTH(i, d_length);
return i;
}
//! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i1, size_t i2 ) const
{
ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2) const {
size_t index = i1 + i2 * d_N[0];
CHECK_ARRAY_LENGTH(index, d_length);
return index;
}
//! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i1, size_t i2, size_t i3 ) const
{
ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2, size_t i3) const {
size_t index = i1 + d_N[0] * (i2 + d_N[1] * i3);
CHECK_ARRAY_LENGTH(index, d_length);
return index;
}
//! Get the index
ARRAY_ATTRIBUTE size_t index( size_t i1, size_t i2, size_t i3, size_t i4 ) const
{
ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2, size_t i3,
size_t i4) const {
size_t index = i1 + d_N[0] * (i2 + d_N[1] * (i3 + d_N[2] * i4));
CHECK_ARRAY_LENGTH(index, d_length);
return index;
}
//! Get the index
ARRAY_ATTRIBUTE size_t
index( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 ) const
{
size_t index = i1 + d_N[0] * ( i2 + d_N[1] * ( i3 + d_N[2] * ( i4 + d_N[3] * i5 ) ) );
ARRAY_ATTRIBUTE size_t index(size_t i1, size_t i2, size_t i3, size_t i4,
size_t i5) const {
size_t index =
i1 + d_N[0] * (i2 + d_N[1] * (i3 + d_N[2] * (i4 + d_N[3] * i5)));
CHECK_ARRAY_LENGTH(index, d_length);
return index;
}
//! Get the index
size_t index( const std::array<size_t, 5> &i ) const
{
size_t index(const std::array<size_t, 5> &i) const {
size_t j = 0;
for (size_t m = 0, N = 1; m < 5; m++) {
j += i[m] * N;
@ -335,8 +305,7 @@ public:
}
//! Get the index
size_t index( std::initializer_list<size_t> i ) const
{
size_t index(std::initializer_list<size_t> i) const {
size_t N = 1;
size_t j = 0;
size_t m = 0;
@ -348,8 +317,7 @@ public:
}
//! Convert the index to ijk values
std::array<size_t, 5> ijk( size_t index ) const
{
std::array<size_t, 5> ijk(size_t index) const {
CHECK_ARRAY_LENGTH(index, d_length);
size_t i0 = index % d_N[0];
index = index / d_N[0];
@ -363,8 +331,7 @@ public:
}
//! Convert the index to ijk values
void ijk( size_t index, size_t *x ) const
{
void ijk(size_t index, size_t *x) const {
CHECK_ARRAY_LENGTH(index, d_length);
x[0] = index % d_N[0];
index = index / d_N[0];
@ -383,10 +350,8 @@ private:
size_t d_N[5];
};
// Function to concatenate dimensions of two array sizes
inline ArraySize cat( const ArraySize &x, const ArraySize &y )
{
inline ArraySize cat(const ArraySize &x, const ArraySize &y) {
if (x.ndim() + y.ndim() > 5)
throw std::out_of_range("Maximum number of dimensions exceeded");
size_t N[5] = {0};
@ -397,30 +362,24 @@ inline ArraySize cat( const ArraySize &x, const ArraySize &y )
return ArraySize(x.ndim() + y.ndim(), N);
}
// Operator overloads
inline ArraySize operator*( size_t v, const ArraySize &x )
{
inline ArraySize operator*(size_t v, const ArraySize &x) {
size_t N[5] = {v * x[0], v * x[1], v * x[2], v * x[3], v * x[4]};
return ArraySize(x.ndim(), N);
}
inline ArraySize operator*( const ArraySize &x, size_t v )
{
inline ArraySize operator*(const ArraySize &x, size_t v) {
size_t N[5] = {v * x[0], v * x[1], v * x[2], v * x[3], v * x[4]};
return ArraySize(x.ndim(), N);
}
inline ArraySize operator-( const ArraySize &x, size_t v )
{
inline ArraySize operator-(const ArraySize &x, size_t v) {
size_t N[5] = {x[0] - v, x[1] - v, x[2] - v, x[3] - v, x[4] - v};
return ArraySize(x.ndim(), N);
}
inline ArraySize operator+( const ArraySize &x, size_t v )
{
inline ArraySize operator+(const ArraySize &x, size_t v) {
size_t N[5] = {x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v};
return ArraySize(x.ndim(), N);
}
inline ArraySize operator+( size_t v, const ArraySize &x )
{
inline ArraySize operator+(size_t v, const ArraySize &x) {
size_t N[5] = {x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v};
return ArraySize(x.ndim(), N);
}
@ -429,5 +388,4 @@ inline ArraySize operator+( size_t v, const ArraySize &x )
ENABLE_WARNINGS
#endif
#endif

View File

@ -1,18 +1,31 @@
#include "common/Communication.h"
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/Communication.h"
/********************************************************
* Structure to store the rank info *
********************************************************/
int RankInfoStruct::getRankForBlock( int i, int j, int k ) const
{
int RankInfoStruct::getRankForBlock(int i, int j, int k) const {
int i2 = (i + nx) % nx;
int j2 = (j + ny) % ny;
int k2 = (k + nz) % nz;
return i2 + j2 * nx + k2 * nx * ny;
}
RankInfoStruct::RankInfoStruct()
{
RankInfoStruct::RankInfoStruct() {
nx = 0;
ny = 0;
nz = 0;
@ -27,8 +40,7 @@ RankInfoStruct::RankInfoStruct()
}
}
}
RankInfoStruct::RankInfoStruct( int rank0, int nprocx, int nprocy, int nprocz )
{
RankInfoStruct::RankInfoStruct(int rank0, int nprocx, int nprocy, int nprocz) {
memset(this, 0, sizeof(RankInfoStruct));
nx = nprocx;
ny = nprocy;
@ -51,7 +63,8 @@ RankInfoStruct::RankInfoStruct( int rank0, int nprocx, int nprocy, int nprocz )
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
rank[i+1][j+1][k+1] = getRankForBlock(ix+i,jy+j,kz+k);
rank[i + 1][j + 1][k + 1] =
getRankForBlock(ix + i, jy + j, kz + k);
}
}
}
@ -59,18 +72,16 @@ RankInfoStruct::RankInfoStruct( int rank0, int nprocx, int nprocy, int nprocz )
}
}
/********************************************************
* Deprecated functions *
********************************************************/
void InitializeRanks( const int rank, const int nprocx, const int nprocy, const int nprocz,
int& iproc, int& jproc, int& kproc,
int& rank_x, int& rank_y, int& rank_z,
int& rank_X, int& rank_Y, int& rank_Z,
int& rank_xy, int& rank_XY, int& rank_xY, int& rank_Xy,
int& rank_xz, int& rank_XZ, int& rank_xZ, int& rank_Xz,
int& rank_yz, int& rank_YZ, int& rank_yZ, int& rank_Yz )
{
void InitializeRanks(const int rank, const int nprocx, const int nprocy,
const int nprocz, int &iproc, int &jproc, int &kproc,
int &rank_x, int &rank_y, int &rank_z, int &rank_X,
int &rank_Y, int &rank_Z, int &rank_xy, int &rank_XY,
int &rank_xY, int &rank_Xy, int &rank_xz, int &rank_XZ,
int &rank_xZ, int &rank_Xz, int &rank_yz, int &rank_YZ,
int &rank_yZ, int &rank_Yz) {
const RankInfoStruct data(rank, nprocx, nprocy, nprocz);
iproc = data.ix;
jproc = data.jy;
@ -94,6 +105,3 @@ void InitializeRanks( const int rank, const int nprocx, const int nprocy, const
rank_Yz = data.rank[1][2][0];
rank_yZ = data.rank[1][0][2];
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMUNICATION_H_INC
#define COMMUNICATION_H_INC
@ -16,7 +32,6 @@
using namespace std;
/*!
* @brief Rank info structure
* @details Structure used to hold the ranks for the current process and it's neighbors
@ -34,20 +49,18 @@ struct RankInfoStruct {
int getRankForBlock(int i, int j, int k) const;
};
//! Redistribute domain data (dst may be smaller than the src)
template <class TYPE>
Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src_data,
const RankInfoStruct& dst_rank, std::array<int,3> dst_size, const Utilities::MPI& comm );
Array<TYPE>
redistribute(const RankInfoStruct &src_rank, const Array<TYPE> &src_data,
const RankInfoStruct &dst_rank, std::array<int, 3> dst_size,
const Utilities::MPI &comm);
/*!
* @brief Communicate halo
* @details Fill the halo cells in an array from the neighboring processes
*/
template<class TYPE>
class fillHalo
{
template <class TYPE> class fillHalo {
public:
/*!
* @brief Default constructor
@ -86,7 +99,6 @@ public:
template <class TYPE1, class TYPE2>
void copy(const Array<TYPE1> &src, Array<TYPE2> &dst);
private:
Utilities::MPI comm;
RankInfoStruct info;
@ -102,9 +114,9 @@ private:
void unpack(Array<TYPE> &array, int i, int j, int k, const TYPE *buffer);
};
//***************************************************************************************
inline void PackMeshData(const int *list, int count, double *sendbuf, double *data){
inline void PackMeshData(const int *list, int count, double *sendbuf,
double *data) {
// Fill in the phase ID values from neighboring processors
// This packs up the values that need to be sent from one processor to another
int idx, n;
@ -113,7 +125,8 @@ inline void PackMeshData(const int *list, int count, double *sendbuf, double *da
sendbuf[idx] = data[n];
}
}
inline void UnpackMeshData(const int *list, int count, double *recvbuf, double *data){
inline void UnpackMeshData(const int *list, int count, double *recvbuf,
double *data) {
// Fill in the phase ID values from neighboring processors
// This unpacks the values once they have been recieved from neighbors
int idx, n;
@ -124,35 +137,31 @@ inline void UnpackMeshData(const int *list, int count, double *recvbuf, double *
}
}
// Initialize the ranks (this is deprecated, see RankInfoStruct)
void InitializeRanks( const int rank, const int nprocx, const int nprocy, const int nprocz,
int& iproc, int& jproc, int& kproc,
int& rank_x, int& rank_y, int& rank_z,
int& rank_X, int& rank_Y, int& rank_Z,
int& rank_xy, int& rank_XY, int& rank_xY, int& rank_Xy,
int& rank_xz, int& rank_XZ, int& rank_xZ, int& rank_Xz,
int& rank_yz, int& rank_YZ, int& rank_yZ, int& rank_Yz );
void InitializeRanks(const int rank, const int nprocx, const int nprocy,
const int nprocz, int &iproc, int &jproc, int &kproc,
int &rank_x, int &rank_y, int &rank_z, int &rank_X,
int &rank_Y, int &rank_Z, int &rank_xy, int &rank_XY,
int &rank_xY, int &rank_Xy, int &rank_xz, int &rank_XZ,
int &rank_xZ, int &rank_Xz, int &rank_yz, int &rank_YZ,
int &rank_yZ, int &rank_Yz);
//***************************************************************************************
inline void CommunicateSendRecvCounts( const Utilities::MPI& comm, int sendtag, int recvtag,
int rank_x, int rank_y, int rank_z,
int rank_X, int rank_Y, int rank_Z,
int rank_xy, int rank_XY, int rank_xY, int rank_Xy,
int rank_xz, int rank_XZ, int rank_xZ, int rank_Xz,
int rank_yz, int rank_YZ, int rank_yZ, int rank_Yz,
int sendCount_x, int sendCount_y, int sendCount_z,
int sendCount_X, int sendCount_Y, int sendCount_Z,
int sendCount_xy, int sendCount_XY, int sendCount_xY, int sendCount_Xy,
int sendCount_xz, int sendCount_XZ, int sendCount_xZ, int sendCount_Xz,
int sendCount_yz, int sendCount_YZ, int sendCount_yZ, int sendCount_Yz,
int& recvCount_x, int& recvCount_y, int& recvCount_z,
int& recvCount_X, int& recvCount_Y, int& recvCount_Z,
int& recvCount_xy, int& recvCount_XY, int& recvCount_xY, int& recvCount_Xy,
int& recvCount_xz, int& recvCount_XZ, int& recvCount_xZ, int& recvCount_Xz,
int& recvCount_yz, int& recvCount_YZ, int& recvCount_yZ, int& recvCount_Yz )
{
inline void CommunicateSendRecvCounts(
const Utilities::MPI &comm, int sendtag, int recvtag, int rank_x,
int rank_y, int rank_z, int rank_X, int rank_Y, int rank_Z, int rank_xy,
int rank_XY, int rank_xY, int rank_Xy, int rank_xz, int rank_XZ,
int rank_xZ, int rank_Xz, int rank_yz, int rank_YZ, int rank_yZ,
int rank_Yz, int sendCount_x, int sendCount_y, int sendCount_z,
int sendCount_X, int sendCount_Y, int sendCount_Z, int sendCount_xy,
int sendCount_XY, int sendCount_xY, int sendCount_Xy, int sendCount_xz,
int sendCount_XZ, int sendCount_xZ, int sendCount_Xz, int sendCount_yz,
int sendCount_YZ, int sendCount_yZ, int sendCount_Yz, int &recvCount_x,
int &recvCount_y, int &recvCount_z, int &recvCount_X, int &recvCount_Y,
int &recvCount_Z, int &recvCount_xy, int &recvCount_XY, int &recvCount_xY,
int &recvCount_Xy, int &recvCount_xz, int &recvCount_XZ, int &recvCount_xZ,
int &recvCount_Xz, int &recvCount_yz, int &recvCount_YZ, int &recvCount_yZ,
int &recvCount_Yz) {
MPI_Request req1[18], req2[18];
req1[0] = comm.Isend(&sendCount_x, 1, rank_x, sendtag + 0);
req2[0] = comm.Irecv(&recvCount_X, 1, rank_X, recvtag + 0);
@ -198,7 +207,6 @@ inline void CommunicateSendRecvCounts( const Utilities::MPI& comm, int sendtag,
comm.barrier();
}
//***************************************************************************************
inline void CommunicateRecvLists( const Utilities::MPI& comm, int sendtag, int recvtag,
int *sendList_x, int *sendList_y, int *sendList_z, int *sendList_X, int *sendList_Y, int *sendList_Z,
@ -264,36 +272,41 @@ inline void CommunicateRecvLists( const Utilities::MPI& comm, int sendtag, int r
comm.waitAll( 18, req2 );
}
//***************************************************************************************
inline void CommunicateMeshHalo(DoubleArray &Mesh, const Utilities::MPI& comm,
double *sendbuf_x,double *sendbuf_y,double *sendbuf_z,double *sendbuf_X,double *sendbuf_Y,double *sendbuf_Z,
double *sendbuf_xy,double *sendbuf_XY,double *sendbuf_xY,double *sendbuf_Xy,
double *sendbuf_xz,double *sendbuf_XZ,double *sendbuf_xZ,double *sendbuf_Xz,
double *sendbuf_yz,double *sendbuf_YZ,double *sendbuf_yZ,double *sendbuf_Yz,
double *recvbuf_x,double *recvbuf_y,double *recvbuf_z,double *recvbuf_X,double *recvbuf_Y,double *recvbuf_Z,
double *recvbuf_xy,double *recvbuf_XY,double *recvbuf_xY,double *recvbuf_Xy,
double *recvbuf_xz,double *recvbuf_XZ,double *recvbuf_xZ,double *recvbuf_Xz,
double *recvbuf_yz,double *recvbuf_YZ,double *recvbuf_yZ,double *recvbuf_Yz,
int *sendList_x,int *sendList_y,int *sendList_z,int *sendList_X,int *sendList_Y,int *sendList_Z,
inline void CommunicateMeshHalo(
DoubleArray &Mesh, const Utilities::MPI &comm, double *sendbuf_x,
double *sendbuf_y, double *sendbuf_z, double *sendbuf_X, double *sendbuf_Y,
double *sendbuf_Z, double *sendbuf_xy, double *sendbuf_XY,
double *sendbuf_xY, double *sendbuf_Xy, double *sendbuf_xz,
double *sendbuf_XZ, double *sendbuf_xZ, double *sendbuf_Xz,
double *sendbuf_yz, double *sendbuf_YZ, double *sendbuf_yZ,
double *sendbuf_Yz, double *recvbuf_x, double *recvbuf_y, double *recvbuf_z,
double *recvbuf_X, double *recvbuf_Y, double *recvbuf_Z, double *recvbuf_xy,
double *recvbuf_XY, double *recvbuf_xY, double *recvbuf_Xy,
double *recvbuf_xz, double *recvbuf_XZ, double *recvbuf_xZ,
double *recvbuf_Xz, double *recvbuf_yz, double *recvbuf_YZ,
double *recvbuf_yZ, double *recvbuf_Yz, int *sendList_x, int *sendList_y,
int *sendList_z, int *sendList_X, int *sendList_Y, int *sendList_Z,
int *sendList_xy, int *sendList_XY, int *sendList_xY, int *sendList_Xy,
int *sendList_xz, int *sendList_XZ, int *sendList_xZ, int *sendList_Xz,
int *sendList_yz, int *sendList_YZ, int *sendList_yZ, int *sendList_Yz,
int sendCount_x,int sendCount_y,int sendCount_z,int sendCount_X,int sendCount_Y,int sendCount_Z,
int sendCount_xy,int sendCount_XY,int sendCount_xY,int sendCount_Xy,
int sendCount_xz,int sendCount_XZ,int sendCount_xZ,int sendCount_Xz,
int sendCount_yz,int sendCount_YZ,int sendCount_yZ,int sendCount_Yz,
int *recvList_x,int *recvList_y,int *recvList_z,int *recvList_X,int *recvList_Y,int *recvList_Z,
int sendCount_x, int sendCount_y, int sendCount_z, int sendCount_X,
int sendCount_Y, int sendCount_Z, int sendCount_xy, int sendCount_XY,
int sendCount_xY, int sendCount_Xy, int sendCount_xz, int sendCount_XZ,
int sendCount_xZ, int sendCount_Xz, int sendCount_yz, int sendCount_YZ,
int sendCount_yZ, int sendCount_Yz, int *recvList_x, int *recvList_y,
int *recvList_z, int *recvList_X, int *recvList_Y, int *recvList_Z,
int *recvList_xy, int *recvList_XY, int *recvList_xY, int *recvList_Xy,
int *recvList_xz, int *recvList_XZ, int *recvList_xZ, int *recvList_Xz,
int *recvList_yz, int *recvList_YZ, int *recvList_yZ, int *recvList_Yz,
int recvCount_x,int recvCount_y,int recvCount_z,int recvCount_X,int recvCount_Y,int recvCount_Z,
int recvCount_xy,int recvCount_XY,int recvCount_xY,int recvCount_Xy,
int recvCount_xz,int recvCount_XZ,int recvCount_xZ,int recvCount_Xz,
int recvCount_yz,int recvCount_YZ,int recvCount_yZ,int recvCount_Yz,
int rank_x,int rank_y,int rank_z,int rank_X,int rank_Y,int rank_Z,int rank_xy,int rank_XY,int rank_xY,
int rank_Xy,int rank_xz,int rank_XZ,int rank_xZ,int rank_Xz,int rank_yz,int rank_YZ,int rank_yZ,int rank_Yz)
{
int recvCount_x, int recvCount_y, int recvCount_z, int recvCount_X,
int recvCount_Y, int recvCount_Z, int recvCount_xy, int recvCount_XY,
int recvCount_xY, int recvCount_Xy, int recvCount_xz, int recvCount_XZ,
int recvCount_xZ, int recvCount_Xz, int recvCount_yz, int recvCount_YZ,
int recvCount_yZ, int recvCount_Yz, int rank_x, int rank_y, int rank_z,
int rank_X, int rank_Y, int rank_Z, int rank_xy, int rank_XY, int rank_xY,
int rank_Xy, int rank_xz, int rank_XZ, int rank_xZ, int rank_Xz,
int rank_yz, int rank_YZ, int rank_yZ, int rank_Yz) {
int sendtag, recvtag;
sendtag = recvtag = 7;
double *MeshData = Mesh.data();
@ -316,24 +329,42 @@ inline void CommunicateMeshHalo(DoubleArray &Mesh, const Utilities::MPI& comm,
PackMeshData(sendList_yZ, sendCount_yZ, sendbuf_yZ, MeshData);
PackMeshData(sendList_YZ, sendCount_YZ, sendbuf_YZ, MeshData);
//......................................................................................
comm.sendrecv(sendbuf_x,sendCount_x,rank_x,sendtag,recvbuf_X,recvCount_X,rank_X,recvtag);
comm.sendrecv(sendbuf_X,sendCount_X,rank_X,sendtag,recvbuf_x,recvCount_x,rank_x,recvtag);
comm.sendrecv(sendbuf_y,sendCount_y,rank_y,sendtag,recvbuf_Y,recvCount_Y,rank_Y,recvtag);
comm.sendrecv(sendbuf_Y,sendCount_Y,rank_Y,sendtag,recvbuf_y,recvCount_y,rank_y,recvtag);
comm.sendrecv(sendbuf_z,sendCount_z,rank_z,sendtag,recvbuf_Z,recvCount_Z,rank_Z,recvtag);
comm.sendrecv(sendbuf_Z,sendCount_Z,rank_Z,sendtag,recvbuf_z,recvCount_z,rank_z,recvtag);
comm.sendrecv(sendbuf_xy,sendCount_xy,rank_xy,sendtag,recvbuf_XY,recvCount_XY,rank_XY,recvtag);
comm.sendrecv(sendbuf_XY,sendCount_XY,rank_XY,sendtag,recvbuf_xy,recvCount_xy,rank_xy,recvtag);
comm.sendrecv(sendbuf_Xy,sendCount_Xy,rank_Xy,sendtag,recvbuf_xY,recvCount_xY,rank_xY,recvtag);
comm.sendrecv(sendbuf_xY,sendCount_xY,rank_xY,sendtag,recvbuf_Xy,recvCount_Xy,rank_Xy,recvtag);
comm.sendrecv(sendbuf_xz,sendCount_xz,rank_xz,sendtag,recvbuf_XZ,recvCount_XZ,rank_XZ,recvtag);
comm.sendrecv(sendbuf_XZ,sendCount_XZ,rank_XZ,sendtag,recvbuf_xz,recvCount_xz,rank_xz,recvtag);
comm.sendrecv(sendbuf_Xz,sendCount_Xz,rank_Xz,sendtag,recvbuf_xZ,recvCount_xZ,rank_xZ,recvtag);
comm.sendrecv(sendbuf_xZ,sendCount_xZ,rank_xZ,sendtag,recvbuf_Xz,recvCount_Xz,rank_Xz,recvtag);
comm.sendrecv(sendbuf_yz,sendCount_yz,rank_yz,sendtag,recvbuf_YZ,recvCount_YZ,rank_YZ,recvtag);
comm.sendrecv(sendbuf_YZ,sendCount_YZ,rank_YZ,sendtag,recvbuf_yz,recvCount_yz,rank_yz,recvtag);
comm.sendrecv(sendbuf_Yz,sendCount_Yz,rank_Yz,sendtag,recvbuf_yZ,recvCount_yZ,rank_yZ,recvtag);
comm.sendrecv(sendbuf_yZ,sendCount_yZ,rank_yZ,sendtag,recvbuf_Yz,recvCount_Yz,rank_Yz,recvtag);
comm.sendrecv(sendbuf_x, sendCount_x, rank_x, sendtag, recvbuf_X,
recvCount_X, rank_X, recvtag);
comm.sendrecv(sendbuf_X, sendCount_X, rank_X, sendtag, recvbuf_x,
recvCount_x, rank_x, recvtag);
comm.sendrecv(sendbuf_y, sendCount_y, rank_y, sendtag, recvbuf_Y,
recvCount_Y, rank_Y, recvtag);
comm.sendrecv(sendbuf_Y, sendCount_Y, rank_Y, sendtag, recvbuf_y,
recvCount_y, rank_y, recvtag);
comm.sendrecv(sendbuf_z, sendCount_z, rank_z, sendtag, recvbuf_Z,
recvCount_Z, rank_Z, recvtag);
comm.sendrecv(sendbuf_Z, sendCount_Z, rank_Z, sendtag, recvbuf_z,
recvCount_z, rank_z, recvtag);
comm.sendrecv(sendbuf_xy, sendCount_xy, rank_xy, sendtag, recvbuf_XY,
recvCount_XY, rank_XY, recvtag);
comm.sendrecv(sendbuf_XY, sendCount_XY, rank_XY, sendtag, recvbuf_xy,
recvCount_xy, rank_xy, recvtag);
comm.sendrecv(sendbuf_Xy, sendCount_Xy, rank_Xy, sendtag, recvbuf_xY,
recvCount_xY, rank_xY, recvtag);
comm.sendrecv(sendbuf_xY, sendCount_xY, rank_xY, sendtag, recvbuf_Xy,
recvCount_Xy, rank_Xy, recvtag);
comm.sendrecv(sendbuf_xz, sendCount_xz, rank_xz, sendtag, recvbuf_XZ,
recvCount_XZ, rank_XZ, recvtag);
comm.sendrecv(sendbuf_XZ, sendCount_XZ, rank_XZ, sendtag, recvbuf_xz,
recvCount_xz, rank_xz, recvtag);
comm.sendrecv(sendbuf_Xz, sendCount_Xz, rank_Xz, sendtag, recvbuf_xZ,
recvCount_xZ, rank_xZ, recvtag);
comm.sendrecv(sendbuf_xZ, sendCount_xZ, rank_xZ, sendtag, recvbuf_Xz,
recvCount_Xz, rank_Xz, recvtag);
comm.sendrecv(sendbuf_yz, sendCount_yz, rank_yz, sendtag, recvbuf_YZ,
recvCount_YZ, rank_YZ, recvtag);
comm.sendrecv(sendbuf_YZ, sendCount_YZ, rank_YZ, sendtag, recvbuf_yz,
recvCount_yz, rank_yz, recvtag);
comm.sendrecv(sendbuf_Yz, sendCount_Yz, rank_Yz, sendtag, recvbuf_yZ,
recvCount_yZ, rank_yZ, recvtag);
comm.sendrecv(sendbuf_yZ, sendCount_yZ, rank_yZ, sendtag, recvbuf_Yz,
recvCount_Yz, rank_Yz, recvtag);
//........................................................................................
UnpackMeshData(recvList_x, recvCount_x, recvbuf_x, MeshData);
UnpackMeshData(recvList_X, recvCount_X, recvbuf_X, MeshData);
@ -355,9 +386,6 @@ inline void CommunicateMeshHalo(DoubleArray &Mesh, const Utilities::MPI& comm,
UnpackMeshData(recvList_YZ, recvCount_YZ, recvbuf_YZ, MeshData);
}
#endif
#include "common/Communication.hpp"

View File

@ -1,3 +1,35 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMUNICATION_HPP_INC
#define COMMUNICATION_HPP_INC
@ -5,30 +37,36 @@
#include "common/MPI.h"
#include "common/Utilities.h"
/********************************************************
* Redistribute data between two grids *
********************************************************/
template <class TYPE>
Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src_data,
const RankInfoStruct& dst_rank, std::array<int,3> dst_size, const Utilities::MPI& comm )
{
Array<TYPE>
redistribute(const RankInfoStruct &src_rank, const Array<TYPE> &src_data,
const RankInfoStruct &dst_rank, std::array<int, 3> dst_size,
const Utilities::MPI &comm) {
if (comm.getSize() == 1) {
return src_data.subset( { 0, (size_t) dst_size[0]-1, 0, (size_t) dst_size[1]-1, 0, (size_t) dst_size[2]-1 } );
return src_data.subset({0, (size_t)dst_size[0] - 1, 0,
(size_t)dst_size[1] - 1, 0,
(size_t)dst_size[2] - 1});
}
// Get the src size
std::array<int, 3> src_size;
int size0[3] = { (int) src_data.size(0), (int) src_data.size(1), (int) src_data.size(2) };
int size0[3] = {(int)src_data.size(0), (int)src_data.size(1),
(int)src_data.size(2)};
comm.maxReduce(size0, src_size.data(), 3);
if (!src_data.empty())
ASSERT( src_size[0] == size0[0] && src_size[1] == size0[1] && src_size[2] == size0[2] );
ASSERT(src_size[0] == size0[0] && src_size[1] == size0[1] &&
src_size[2] == size0[2]);
// Check that dst_size matches on all ranks
comm.maxReduce(dst_size.data(), size0, 3);
ASSERT( dst_size[0] == size0[0] && dst_size[1] == size0[1] && dst_size[2] == size0[2] );
ASSERT(dst_size[0] == size0[0] && dst_size[1] == size0[1] &&
dst_size[2] == size0[2]);
// Function to get overlap range
auto calcOverlap = [](int i1[3], int i2[3], int j1[3], int j2[3]) {
std::vector<size_t> index;
if ( i1[0] > j2[0] || i2[0] < j1[0] || i1[1] > j2[1] || i2[1] < j1[1] || i1[2] > j2[2] || i2[2] < j1[2] )
if (i1[0] > j2[0] || i2[0] < j1[0] || i1[1] > j2[1] || i2[1] < j1[1] ||
i1[2] > j2[2] || i2[2] < j1[2])
return index;
index.resize(6);
index[0] = std::max(j1[0] - i1[0], 0);
@ -43,13 +81,18 @@ Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src
std::vector<int> send_rank;
std::vector<Array<TYPE>> send_data;
if (!src_data.empty()) {
int i1[3] = { src_size[0] * src_rank.ix, src_size[1] * src_rank.jy, src_size[2] * src_rank.kz };
int i2[3] = { i1[0] + src_size[0] - 1, i1[1] + src_size[1] - 1, i1[2] + src_size[2] - 1 };
int i1[3] = {src_size[0] * src_rank.ix, src_size[1] * src_rank.jy,
src_size[2] * src_rank.kz};
int i2[3] = {i1[0] + src_size[0] - 1, i1[1] + src_size[1] - 1,
i1[2] + src_size[2] - 1};
for (int i = 0; i < dst_rank.nx; i++) {
for (int j = 0; j < dst_rank.ny; j++) {
for (int k = 0; k < dst_rank.nz; k++) {
int j1[3] = { i * dst_size[0], j * dst_size[1], k * dst_size[2] };
int j2[3] = { j1[0] + dst_size[0] - 1, j1[1] + dst_size[1] - 1, j1[2] + dst_size[2] - 1 };
int j1[3] = {i * dst_size[0], j * dst_size[1],
k * dst_size[2]};
int j2[3] = {j1[0] + dst_size[0] - 1,
j1[1] + dst_size[1] - 1,
j1[2] + dst_size[2] - 1};
auto index = calcOverlap(i1, i2, j1, j2);
if (index.empty())
continue;
@ -61,21 +104,27 @@ Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src
}
std::vector<MPI_Request> send_request(send_rank.size());
for (size_t i = 0; i < send_rank.size(); i++)
send_request[i] = comm.Isend( send_data[i].data(), send_data[i].length(), send_rank[i], 5462 );
send_request[i] = comm.Isend(send_data[i].data(), send_data[i].length(),
send_rank[i], 5462);
// Unpack data from the appropriate ranks (including myself)
Array<TYPE> dst_data(dst_size[0], dst_size[1], dst_size[2]);
int i1[3] = { dst_size[0] * dst_rank.ix, dst_size[1] * dst_rank.jy, dst_size[2] * dst_rank.kz };
int i2[3] = { i1[0] + dst_size[0] - 1, i1[1] + dst_size[1] - 1, i1[2] + dst_size[2] - 1 };
int i1[3] = {dst_size[0] * dst_rank.ix, dst_size[1] * dst_rank.jy,
dst_size[2] * dst_rank.kz};
int i2[3] = {i1[0] + dst_size[0] - 1, i1[1] + dst_size[1] - 1,
i1[2] + dst_size[2] - 1};
for (int i = 0; i < src_rank.nx; i++) {
for (int j = 0; j < src_rank.ny; j++) {
for (int k = 0; k < src_rank.nz; k++) {
int j1[3] = {i * src_size[0], j * src_size[1], k * src_size[2]};
int j2[3] = { j1[0] + src_size[0] - 1, j1[1] + src_size[1] - 1, j1[2] + src_size[2] - 1 };
int j2[3] = {j1[0] + src_size[0] - 1, j1[1] + src_size[1] - 1,
j1[2] + src_size[2] - 1};
auto index = calcOverlap(i1, i2, j1, j2);
if (index.empty())
continue;
int rank = src_rank.getRankForBlock(i, j, k);
Array<TYPE> data( index[1] - index[0] + 1, index[3] - index[2] + 1, index[5] - index[4] + 1 );
Array<TYPE> data(index[1] - index[0] + 1,
index[3] - index[2] + 1,
index[5] - index[4] + 1);
comm.recv(data.data(), data.length(), rank, 5462);
dst_data.copySubset(index, data);
}
@ -86,17 +135,15 @@ Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src
return dst_data;
}
/********************************************************
* Structure to fill halo cells *
********************************************************/
template <class TYPE>
fillHalo<TYPE>::fillHalo( const Utilities::MPI& comm_, const RankInfoStruct& info_,
std::array<int,3> n_, std::array<int,3> ng_, int tag0, int depth_,
std::array<bool,3> fill, std::array<bool,3> periodic ):
comm(comm_), info(info_), n(n_), ng(ng_), depth(depth_)
{
fillHalo<TYPE>::fillHalo(const Utilities::MPI &comm_,
const RankInfoStruct &info_, std::array<int, 3> n_,
std::array<int, 3> ng_, int tag0, int depth_,
std::array<bool, 3> fill, std::array<bool, 3> periodic)
: comm(comm_), info(info_), n(n_), ng(ng_), depth(depth_) {
// Set the fill pattern
memset(fill_pattern, 0, sizeof(fill_pattern));
if (fill[0]) {
@ -210,16 +257,9 @@ fillHalo<TYPE>::fillHalo( const Utilities::MPI& comm_, const RankInfoStruct& inf
}
}
}
}
template<class TYPE>
fillHalo<TYPE>::~fillHalo( )
{
delete [] mem;
}
template<class TYPE>
void fillHalo<TYPE>::fill( Array<TYPE>& data )
{
template <class TYPE> fillHalo<TYPE>::~fillHalo() { delete[] mem; }
template <class TYPE> void fillHalo<TYPE>::fill(Array<TYPE> &data) {
//PROFILE_START("fillHalo::fill",1);
int depth2 = data.size(3);
ASSERT((int)data.size(0) == n[0] + 2 * ng[0]);
@ -233,7 +273,8 @@ void fillHalo<TYPE>::fill( Array<TYPE>& data )
for (int k = 0; k < 3; k++) {
if (!fill_pattern[i][j][k])
continue;
recv_req[i][j][k] = comm.Irecv( recv[i][j][k], depth2*N_send_recv[i][j][k],
recv_req[i][j][k] =
comm.Irecv(recv[i][j][k], depth2 * N_send_recv[i][j][k],
info.rank[i][j][k], tag[2 - i][2 - j][2 - k]);
}
}
@ -245,7 +286,8 @@ void fillHalo<TYPE>::fill( Array<TYPE>& data )
if (!fill_pattern[i][j][k])
continue;
pack(data, i - 1, j - 1, k - 1, send[i][j][k]);
send_req[i][j][k] = comm.Isend( send[i][j][k], depth2*N_send_recv[i][j][k],
send_req[i][j][k] =
comm.Isend(send[i][j][k], depth2 * N_send_recv[i][j][k],
info.rank[i][j][k], tag[i][j][k]);
}
}
@ -274,8 +316,8 @@ void fillHalo<TYPE>::fill( Array<TYPE>& data )
//PROFILE_STOP("fillHalo::fill",1);
}
template <class TYPE>
void fillHalo<TYPE>::pack( const Array<TYPE>& data, int i0, int j0, int k0, TYPE *buffer )
{
void fillHalo<TYPE>::pack(const Array<TYPE> &data, int i0, int j0, int k0,
TYPE *buffer) {
int depth2 = data.size(3);
int ni = i0 == 0 ? n[0] : ng[0];
int nj = j0 == 0 ? n[1] : ng[1];
@ -287,15 +329,16 @@ void fillHalo<TYPE>::pack( const Array<TYPE>& data, int i0, int j0, int k0, TYPE
for (int k = 0; k < nk; k++) {
for (int j = 0; j < nj; j++) {
for (int i = 0; i < ni; i++) {
buffer[i+j*ni+k*ni*nj+d*ni*nj*nk] = data(i+is,j+js,k+ks,d);
buffer[i + j * ni + k * ni * nj + d * ni * nj * nk] =
data(i + is, j + js, k + ks, d);
}
}
}
}
}
template <class TYPE>
void fillHalo<TYPE>::unpack( Array<TYPE>& data, int i0, int j0, int k0, const TYPE *buffer )
{
void fillHalo<TYPE>::unpack(Array<TYPE> &data, int i0, int j0, int k0,
const TYPE *buffer) {
int depth2 = data.size(3);
int ni = i0 == 0 ? n[0] : ng[0];
int nj = j0 == 0 ? n[1] : ng[1];
@ -307,21 +350,20 @@ void fillHalo<TYPE>::unpack( Array<TYPE>& data, int i0, int j0, int k0, const TY
for (int k = 0; k < nk; k++) {
for (int j = 0; j < nj; j++) {
for (int i = 0; i < ni; i++) {
data(i+is,j+js,k+ks,d) = buffer[i+j*ni+k*ni*nj+d*ni*nj*nk];
data(i + is, j + js, k + ks, d) =
buffer[i + j * ni + k * ni * nj + d * ni * nj * nk];
}
}
}
}
}
/********************************************************
* Function to remove the ghost halo *
********************************************************/
template <class TYPE>
template <class TYPE1, class TYPE2>
void fillHalo<TYPE>::copy( const Array<TYPE1>& src, Array<TYPE2>& dst )
{
void fillHalo<TYPE>::copy(const Array<TYPE1> &src, Array<TYPE2> &dst) {
//PROFILE_START("fillHalo::copy",1);
ASSERT((int)src.size(0) == n[0] || (int)src.size(0) == n[0] + 2 * ng[0]);
ASSERT((int)dst.size(0) == n[0] || (int)dst.size(0) == n[0] + 2 * ng[0]);
@ -372,5 +414,4 @@ void fillHalo<TYPE>::copy( const Array<TYPE1>& src, Array<TYPE2>& dst )
//PROFILE_STOP("fillHalo::copy",1);
}
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/Database.h"
#include "common/Utilities.h"
@ -8,20 +24,17 @@
#include <string>
#include <tuple>
/********************************************************************
* Constructors/destructor *
********************************************************************/
Database::Database() = default;
Database::~Database() = default;
Database::Database( const Database& rhs ) : KeyData( rhs )
{
Database::Database(const Database &rhs) : KeyData(rhs) {
d_data.clear();
for (const auto &tmp : rhs.d_data)
putData(tmp.first, tmp.second->clone());
}
Database& Database::operator=( const Database& rhs )
{
Database &Database::operator=(const Database &rhs) {
if (this == &rhs)
return *this;
d_data.clear();
@ -30,36 +43,30 @@ Database& Database::operator=( const Database& rhs )
return *this;
}
Database::Database(Database &&rhs) { std::swap(d_data, rhs.d_data); }
Database& Database::operator=( Database&& rhs )
{
Database &Database::operator=(Database &&rhs) {
if (this != &rhs)
std::swap(d_data, rhs.d_data);
return *this;
}
/********************************************************************
* Clone the database *
********************************************************************/
std::shared_ptr<KeyData> Database::clone() const { return cloneDatabase(); }
std::shared_ptr<Database> Database::cloneDatabase() const
{
std::shared_ptr<Database> Database::cloneDatabase() const {
auto db = std::make_shared<Database>();
for (const auto &tmp : d_data)
db->putData(tmp.first, tmp.second->clone());
return db;
}
/********************************************************************
* Get the data object *
********************************************************************/
bool Database::keyExists( const std::string& key ) const
{
bool Database::keyExists(const std::string &key) const {
return d_data.find(key) != d_data.end();
}
std::shared_ptr<KeyData> Database::getData( const std::string& key )
{
std::shared_ptr<KeyData> Database::getData(const std::string &key) {
auto it = d_data.find(key);
if (it == d_data.end()) {
char msg[1000];
@ -68,18 +75,15 @@ std::shared_ptr<KeyData> Database::getData( const std::string& key )
}
return it->second;
}
std::shared_ptr<const KeyData> Database::getData( const std::string& key ) const
{
std::shared_ptr<const KeyData> Database::getData(const std::string &key) const {
return const_cast<Database *>(this)->getData(key);
}
bool Database::isDatabase( const std::string& key ) const
{
bool Database::isDatabase(const std::string &key) const {
auto ptr = getData(key);
auto ptr2 = std::dynamic_pointer_cast<const Database>(ptr);
return ptr2 != nullptr;
}
std::shared_ptr<Database> Database::getDatabase( const std::string& key )
{
std::shared_ptr<Database> Database::getDatabase(const std::string &key) {
std::shared_ptr<KeyData> ptr = getData(key);
std::shared_ptr<Database> ptr2 = std::dynamic_pointer_cast<Database>(ptr);
if (ptr2 == nullptr) {
@ -89,46 +93,37 @@ std::shared_ptr<Database> Database::getDatabase( const std::string& key )
}
return ptr2;
}
std::shared_ptr<const Database> Database::getDatabase( const std::string& key ) const
{
std::shared_ptr<const Database>
Database::getDatabase(const std::string &key) const {
return const_cast<Database *>(this)->getDatabase(key);
}
std::vector<std::string> Database::getAllKeys() const
{
std::vector<std::string> Database::getAllKeys() const {
std::vector<std::string> keys;
keys.reserve(d_data.size());
for (const auto &it : d_data)
keys.push_back(it.first);
return keys;
}
void Database::putDatabase( const std::string& key, std::shared_ptr<Database> db )
{
void Database::putDatabase(const std::string &key,
std::shared_ptr<Database> db) {
d_data[key] = std::move(db);
}
void Database::putData( const std::string& key, std::shared_ptr<KeyData> data )
{
void Database::putData(const std::string &key, std::shared_ptr<KeyData> data) {
d_data[key] = std::move(data);
}
/********************************************************************
* Is the data of the given type *
********************************************************************/
template<>
bool Database::isType<double>( const std::string& key ) const
{
template <> bool Database::isType<double>(const std::string &key) const {
auto type = getData(key)->type();
return type == "double";
}
template<>
bool Database::isType<float>( const std::string& key ) const
{
template <> bool Database::isType<float>(const std::string &key) const {
auto type = getData(key)->type();
return type == "double";
}
template<>
bool Database::isType<int>( const std::string& key ) const
{
template <> bool Database::isType<int>(const std::string &key) const {
bool pass = true;
auto type = getData(key)->type();
if (type == "double") {
@ -140,27 +135,21 @@ bool Database::isType<int>( const std::string& key ) const
}
return pass;
}
template<>
bool Database::isType<std::string>( const std::string& key ) const
{
template <> bool Database::isType<std::string>(const std::string &key) const {
auto type = getData(key)->type();
return type == "string";
}
template<>
bool Database::isType<bool>( const std::string& key ) const
{
template <> bool Database::isType<bool>(const std::string &key) const {
auto type = getData(key)->type();
return type == "bool";
}
/********************************************************************
* Get a vector *
********************************************************************/
template <>
std::vector<std::string> Database::getVector<std::string>(
const std::string& key, const Units& ) const
{
std::vector<std::string>
Database::getVector<std::string>(const std::string &key, const Units &) const {
std::shared_ptr<const KeyData> ptr = getData(key);
if (std::dynamic_pointer_cast<const EmptyKeyData>(ptr))
return std::vector<std::string>();
@ -171,8 +160,8 @@ std::vector<std::string> Database::getVector<std::string>(
return ptr2->d_data;
}
template <>
std::vector<bool> Database::getVector<bool>( const std::string& key, const Units& ) const
{
std::vector<bool> Database::getVector<bool>(const std::string &key,
const Units &) const {
std::shared_ptr<const KeyData> ptr = getData(key);
if (std::dynamic_pointer_cast<const EmptyKeyData>(ptr))
return std::vector<bool>();
@ -183,8 +172,8 @@ std::vector<bool> Database::getVector<bool>( const std::string& key, const Units
return ptr2->d_data;
}
template <class TYPE>
std::vector<TYPE> Database::getVector( const std::string& key, const Units& unit ) const
{
std::vector<TYPE> Database::getVector(const std::string &key,
const Units &unit) const {
std::shared_ptr<const KeyData> ptr = getData(key);
if (std::dynamic_pointer_cast<const EmptyKeyData>(ptr))
return std::vector<TYPE>();
@ -211,29 +200,27 @@ std::vector<TYPE> Database::getVector( const std::string& key, const Units& unit
return data;
}
/********************************************************************
* Put a vector *
********************************************************************/
template <>
void Database::putVector<std::string>(
const std::string& key, const std::vector<std::string>& data, const Units& )
{
void Database::putVector<std::string>(const std::string &key,
const std::vector<std::string> &data,
const Units &) {
std::shared_ptr<KeyDataString> ptr(new KeyDataString());
ptr->d_data = data;
d_data[key] = ptr;
}
template <>
void Database::putVector<bool>(
const std::string& key, const std::vector<bool>& data, const Units& )
{
void Database::putVector<bool>(const std::string &key,
const std::vector<bool> &data, const Units &) {
std::shared_ptr<KeyDataBool> ptr(new KeyDataBool());
ptr->d_data = data;
d_data[key] = ptr;
}
template <class TYPE>
void Database::putVector( const std::string& key, const std::vector<TYPE>& data, const Units& unit )
{
void Database::putVector(const std::string &key, const std::vector<TYPE> &data,
const Units &unit) {
std::shared_ptr<KeyDataDouble> ptr(new KeyDataDouble());
ptr->d_unit = unit;
ptr->d_data.resize(data.size());
@ -242,12 +229,10 @@ void Database::putVector( const std::string& key, const std::vector<TYPE>& data,
d_data[key] = ptr;
}
/********************************************************************
* Print the database *
********************************************************************/
void Database::print( std::ostream& os, const std::string& indent ) const
{
void Database::print(std::ostream &os, const std::string &indent) const {
for (const auto &it : d_data) {
os << indent << it.first;
if (dynamic_cast<const Database *>(it.second.get())) {
@ -261,19 +246,16 @@ void Database::print( std::ostream& os, const std::string& indent ) const
}
}
}
std::string Database::print( const std::string& indent ) const
{
std::string Database::print(const std::string &indent) const {
std::stringstream ss;
print(ss, indent);
return ss.str();
}
/********************************************************************
* Read input database file *
********************************************************************/
Database::Database( const std::string& filename )
{
Database::Database(const std::string &filename) {
// Read the input file into memory
FILE *fid = fopen(filename.c_str(), "rb");
if (fid == nullptr)
@ -295,8 +277,7 @@ Database::Database( const std::string& filename )
// Free temporary memory
delete[] buffer;
}
std::shared_ptr<Database> Database::createFromString( const std::string& data )
{
std::shared_ptr<Database> Database::createFromString(const std::string &data) {
std::shared_ptr<Database> db(new Database());
auto *buffer = new char[data.size() + 4];
memcpy(buffer, data.data(), data.size());
@ -319,21 +300,20 @@ enum class token_type {
end_bracket,
end
};
inline size_t length( token_type type )
{
inline size_t length(token_type type) {
size_t len = 0;
if ( type == token_type::newline || type == token_type::quote || type == token_type::equal ||
type == token_type::bracket || type == token_type::end_bracket ||
type == token_type::end ) {
if (type == token_type::newline || type == token_type::quote ||
type == token_type::equal || type == token_type::bracket ||
type == token_type::end_bracket || type == token_type::end) {
len = 1;
} else if ( type == token_type::line_comment || type == token_type::block_start ||
} else if (type == token_type::line_comment ||
type == token_type::block_start ||
type == token_type::block_stop) {
len = 2;
}
return len;
}
inline std::tuple<size_t, token_type> find_next_token( const char* buffer )
{
inline std::tuple<size_t, token_type> find_next_token(const char *buffer) {
size_t i = 0;
while (true) {
if (buffer[i] == '\n' || buffer[i] == '\r') {
@ -347,23 +327,26 @@ inline std::tuple<size_t, token_type> find_next_token( const char* buffer )
} else if (buffer[i] == '{') {
return std::pair<size_t, token_type>(i + 1, token_type::bracket);
} else if (buffer[i] == '}') {
return std::pair<size_t, token_type>( i + 1, token_type::end_bracket );
return std::pair<size_t, token_type>(i + 1,
token_type::end_bracket);
} else if (buffer[i] == '/') {
if (buffer[i + 1] == '/') {
return std::pair<size_t, token_type>( i + 2, token_type::line_comment );
return std::pair<size_t, token_type>(i + 2,
token_type::line_comment);
} else if (buffer[i + 1] == '*') {
return std::pair<size_t, token_type>( i + 2, token_type::block_start );
return std::pair<size_t, token_type>(i + 2,
token_type::block_start);
}
} else if (buffer[i] == '*') {
if (buffer[i + 1] == '/')
return std::pair<size_t, token_type>( i + 2, token_type::block_stop );
return std::pair<size_t, token_type>(i + 2,
token_type::block_stop);
}
i++;
}
return std::pair<size_t, token_type>(0, token_type::end);
}
inline std::string deblank( const std::string& str )
{
inline std::string deblank(const std::string &str) {
size_t i1 = 0xFFFFFFF, i2 = 0;
for (size_t i = 0; i < str.size(); i++) {
if (str[i] != ' ') {
@ -373,12 +356,11 @@ inline std::string deblank( const std::string& str )
}
return i1 <= i2 ? str.substr(i1, i2 - i1 + 1) : std::string();
}
size_t skip_comment( const char* buffer )
{
size_t skip_comment(const char *buffer) {
auto tmp = find_next_token(buffer);
const token_type end_comment = ( std::get<1>( tmp ) == token_type::line_comment ) ?
token_type::newline :
token_type::block_stop;
const token_type end_comment =
(std::get<1>(tmp) == token_type::line_comment) ? token_type::newline
: token_type::block_stop;
size_t pos = 0;
while (std::get<1>(tmp) != end_comment) {
if (std::get<1>(tmp) == token_type::end)
@ -389,15 +371,13 @@ size_t skip_comment( const char* buffer )
pos += std::get<0>(tmp);
return pos;
}
inline std::string lower( const std::string& str )
{
inline std::string lower(const std::string &str) {
std::string tmp(str);
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
return tmp;
}
static std::tuple<size_t, std::shared_ptr<KeyData>> read_value(
const char* buffer, const std::string& key )
{
static std::tuple<size_t, std::shared_ptr<KeyData>>
read_value(const char *buffer, const std::string &key) {
// Get the value as a std::string
size_t pos = 0;
token_type type = token_type::end;
@ -413,7 +393,8 @@ static std::tuple<size_t, std::shared_ptr<KeyData>> read_value(
std::tie(i, type) = find_next_token(&buffer[pos]);
pos += i;
}
} else if ( type == token_type::line_comment || type == token_type::block_start ) {
} else if (type == token_type::line_comment ||
type == token_type::block_start) {
len = pos - length(type);
pos += skip_comment(&buffer[pos - length(type)]) - length(type);
break;
@ -446,7 +427,8 @@ static std::tuple<size_t, std::shared_ptr<KeyData>> read_value(
data2->d_data.resize(values.size());
for (size_t i = 0; i < values.size(); i++) {
ASSERT(values[i].size() >= 2);
ASSERT( values[i][0] == '"' && values[i][values[i].size() - 1] == '"' );
ASSERT(values[i][0] == '"' &&
values[i][values[i].size() - 1] == '"');
data2->d_data[i] = values[i].substr(1, values[i].size() - 2);
}
} else if (lower(value) == "true" || lower(value) == "false") {
@ -474,16 +456,16 @@ static std::tuple<size_t, std::shared_ptr<KeyData>> read_value(
}
return std::tuple<size_t, std::shared_ptr<KeyData>>(pos, data);
}
size_t Database::loadDatabase( const char* buffer, Database& db )
{
size_t Database::loadDatabase(const char *buffer, Database &db) {
size_t pos = 0;
while (true) {
size_t i;
token_type type;
std::tie(i, type) = find_next_token(&buffer[pos]);
const std::string key =
deblank( std::string( &buffer[pos], std::max<int>( i - length( type ), 1 ) - 1 ) );
if ( type == token_type::line_comment || type == token_type::block_start ) {
const std::string key = deblank(
std::string(&buffer[pos], std::max<int>(i - length(type), 1) - 1));
if (type == token_type::line_comment ||
type == token_type::block_start) {
// Comment
INSIST(key.empty(), "Key should be empty: " + key);
pos += skip_comment(&buffer[pos]);
@ -517,12 +499,10 @@ size_t Database::loadDatabase( const char* buffer, Database& db )
return pos;
}
/********************************************************************
* Data type helper functions *
********************************************************************/
void KeyDataDouble::print( std::ostream& os, const std::string& indent ) const
{
void KeyDataDouble::print(std::ostream &os, const std::string &indent) const {
os << indent;
for (size_t i = 0; i < d_data.size(); i++) {
if (i > 0)
@ -541,19 +521,17 @@ void KeyDataDouble::print( std::ostream& os, const std::string& indent ) const
os << " " << d_unit.str();
os << std::endl;
}
std::tuple<double, Units> KeyDataDouble::read( const std::string& str )
{
std::tuple<double, Units> KeyDataDouble::read(const std::string &str) {
std::string tmp = deblank(str);
size_t index = tmp.find(" ");
if (index != std::string::npos) {
return std::make_tuple(
readValue( tmp.substr( 0, index ) ), Units( tmp.substr( index + 1 ) ) );
return std::make_tuple(readValue(tmp.substr(0, index)),
Units(tmp.substr(index + 1)));
} else {
return std::make_tuple(readValue(tmp), Units());
}
}
double KeyDataDouble::readValue( const std::string& str )
{
double KeyDataDouble::readValue(const std::string &str) {
const std::string tmp = lower(str);
double data = 0;
if (tmp == "inf" || tmp == "infinity") {
@ -573,24 +551,33 @@ double KeyDataDouble::readValue( const std::string& str )
return data;
}
/********************************************************************
* Instantiations *
********************************************************************/
template std::vector<char> Database::getVector<char>( const std::string&, const Units& ) const;
template std::vector<int> Database::getVector<int>( const std::string&, const Units& ) const;
template std::vector<size_t> Database::getVector<size_t>( const std::string&, const Units& ) const;
template std::vector<float> Database::getVector<float>( const std::string&, const Units& ) const;
template std::vector<double> Database::getVector<double>( const std::string&, const Units& ) const;
template void Database::putVector<char>(
const std::string&, const std::vector<char>&, const Units& );
template void Database::putVector<int>( const std::string&, const std::vector<int>&, const Units& );
template void Database::putVector<size_t>(
const std::string&, const std::vector<size_t>&, const Units& );
template void Database::putVector<float>(
const std::string&, const std::vector<float>&, const Units& );
template void Database::putVector<double>(
const std::string&, const std::vector<double>&, const Units& );
template std::vector<char> Database::getVector<char>(const std::string &,
const Units &) const;
template std::vector<int> Database::getVector<int>(const std::string &,
const Units &) const;
template std::vector<size_t> Database::getVector<size_t>(const std::string &,
const Units &) const;
template std::vector<float> Database::getVector<float>(const std::string &,
const Units &) const;
template std::vector<double> Database::getVector<double>(const std::string &,
const Units &) const;
template void Database::putVector<char>(const std::string &,
const std::vector<char> &,
const Units &);
template void Database::putVector<int>(const std::string &,
const std::vector<int> &, const Units &);
template void Database::putVector<size_t>(const std::string &,
const std::vector<size_t> &,
const Units &);
template void Database::putVector<float>(const std::string &,
const std::vector<float> &,
const Units &);
template void Database::putVector<double>(const std::string &,
const std::vector<double> &,
const Units &);
template bool Database::isType<int>(const std::string &) const;
template bool Database::isType<float>(const std::string &) const;
template bool Database::isType<double>(const std::string &) const;

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_Database
#define included_Database
@ -10,17 +26,13 @@
#include "common/Units.h"
inline bool exists( const std::string& filename )
{
inline bool exists(const std::string &filename) {
std::ifstream domain(filename);
return domain.good();
}
//! Base class to hold data of a given type
class KeyData
{
class KeyData {
protected:
//! Empty constructor
KeyData() {}
@ -31,7 +43,8 @@ public:
//! Copy the data
virtual std::shared_ptr<KeyData> clone() const = 0;
//! Print the data to a stream
virtual void print( std::ostream& os, const std::string& indent = "" ) const = 0;
virtual void print(std::ostream &os,
const std::string &indent = "") const = 0;
//! Return the native data type
virtual std::string type() const = 0;
@ -40,10 +53,8 @@ protected:
KeyData &operator=(const KeyData &);
};
//! Class to a database
class Database : public KeyData
{
class Database : public KeyData {
public:
//! Empty constructor
Database();
@ -81,7 +92,6 @@ public:
//! Copy the data
std::shared_ptr<Database> cloneDatabase() const;
/**
* Return true if the specified key exists in the database and false
* otherwise.
@ -89,17 +99,14 @@ public:
*/
bool keyExists(const std::string &key) const;
/**
* Return all keys in the database.
*/
std::vector<std::string> getAllKeys() const;
//! Return the number of entries in the database
size_t size() const { return d_data.size(); }
/**
* Get the scalar entry from the database with the specified key
* name. If the specified key does not exist in the database or
@ -110,13 +117,13 @@ public:
* @param[in] unit Desired units
*/
template <class TYPE>
inline TYPE getScalar( const std::string& key, const Units& unit = Units() ) const;
inline TYPE getScalar(const std::string &key,
const Units &unit = Units()) const;
/// @copydoc Database::getScalar(const std::string&,const Units&) const
template <class TYPE>
inline TYPE getScalar( const std::string& key, const std::string& unit ) const;
inline TYPE getScalar(const std::string &key,
const std::string &unit) const;
/**
* Get the scalar entry from the database with the specified key
@ -128,15 +135,13 @@ public:
* @param[in] unit Desired units
*/
template <class TYPE>
inline TYPE getWithDefault(
const std::string& key, const TYPE& value, const Units& unit = Units() ) const;
inline TYPE getWithDefault(const std::string &key, const TYPE &value,
const Units &unit = Units()) const;
/// @copydoc Database::getWithDefault(const std::string&,const TYPE&,const Units&) const
template <class TYPE>
inline TYPE getWithDefault(
const std::string& key, const TYPE& value, const std::string& unit ) const;
inline TYPE getWithDefault(const std::string &key, const TYPE &value,
const std::string &unit) const;
/**
* Put the scalar entry into the database with the specified key name.
@ -145,8 +150,8 @@ public:
* @param unit Desired units
*/
template <class TYPE>
inline void putScalar( const std::string& key, const TYPE& value, const Units& unit = Units() );
inline void putScalar(const std::string &key, const TYPE &value,
const Units &unit = Units());
/**
* Put the scalar entry into the database with the specified key name.
@ -155,8 +160,8 @@ public:
* @param unit Desired units
*/
template <class TYPE>
inline void putScalar( const std::string& key, const TYPE& value, const std::string& unit );
inline void putScalar(const std::string &key, const TYPE &value,
const std::string &unit);
/**
* Get the vector entries from the database with the specified key
@ -168,13 +173,13 @@ public:
* @param unit Desired units
*/
template <class TYPE>
std::vector<TYPE> getVector( const std::string& key, const Units& unit = Units() ) const;
std::vector<TYPE> getVector(const std::string &key,
const Units &unit = Units()) const;
/// @copydoc Database::getVector(const std::string&,const Units&) const
template <class TYPE>
inline std::vector<TYPE> getVector( const std::string& key, const std::string& unit ) const;
inline std::vector<TYPE> getVector(const std::string &key,
const std::string &unit) const;
/**
* Put the vector entries into the database with the specified key
@ -187,15 +192,13 @@ public:
* @param unit Desired units
*/
template <class TYPE>
void putVector(
const std::string& key, const std::vector<TYPE>& data, const Units& unit = Units() );
void putVector(const std::string &key, const std::vector<TYPE> &data,
const Units &unit = Units());
/// @copydoc Database::putVector(const std::string&,const std::vector<TYPE>&,const Units&)
template <class TYPE>
inline void putVector(
const std::string& key, const std::vector<TYPE>& data, const std::string& unit );
inline void putVector(const std::string &key, const std::vector<TYPE> &data,
const std::string &unit);
/**
* Get the data for a key in the database. If the specified key
@ -215,7 +218,6 @@ public:
*/
std::shared_ptr<const KeyData> getData(const std::string &key) const;
/**
* Put the data for a key in the database.
*
@ -224,15 +226,11 @@ public:
*/
void putData(const std::string &key, std::shared_ptr<KeyData> data);
// Check if the key is a database object
bool isDatabase(const std::string &key) const;
// Check if the entry can be stored as the given type
template<class TYPE>
bool isType( const std::string& key ) const;
template <class TYPE> bool isType(const std::string &key) const;
/**
* Get the database for a key in the database. If the specified key
@ -252,7 +250,6 @@ public:
*/
std::shared_ptr<const Database> getDatabase(const std::string &key) const;
/**
* Get the database for a key in the database. If the specified key
* does not exist in the database an error message is printed and
@ -263,26 +260,23 @@ public:
*/
void putDatabase(const std::string &key, std::shared_ptr<Database> db);
/**
* Print the data to a stream
* @param os Output stream
* @param indent Indenting to use before each line
*/
virtual void print( std::ostream& os, const std::string& indent = "" ) const override;
virtual void print(std::ostream &os,
const std::string &indent = "") const override;
//! Print the type
virtual std::string type() const override { return "database"; }
/**
* Print the data to a string
* @return Output string
*/
std::string print(const std::string &indent = "") const;
protected:
std::map<std::string, std::shared_ptr<KeyData>> d_data;
@ -290,7 +284,6 @@ protected:
static size_t loadDatabase(const char *buffer, Database &db);
};
#include "common/Database.hpp"
#endif

View File

@ -1,3 +1,35 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_Database_hpp
#define included_Database_hpp
@ -6,39 +38,33 @@
#include <tuple>
/********************************************************************
* Basic classes for primative data types *
********************************************************************/
class EmptyKeyData : public KeyData
{
class EmptyKeyData : public KeyData {
public:
EmptyKeyData() {}
virtual ~EmptyKeyData() {}
virtual std::shared_ptr<KeyData> clone() const override
{
virtual std::shared_ptr<KeyData> clone() const override {
return std::make_shared<EmptyKeyData>();
}
virtual void print( std::ostream& os, const std::string& = "" ) const override
{
virtual void print(std::ostream &os,
const std::string & = "") const override {
os << std::endl;
}
virtual std::string type() const override { return ""; }
};
class KeyDataDouble : public KeyData
{
class KeyDataDouble : public KeyData {
public:
KeyDataDouble() {}
explicit KeyDataDouble(const std::vector<double> &data, const Units &unit)
: d_data( data ), d_unit( unit )
{
}
: d_data(data), d_unit(unit) {}
virtual ~KeyDataDouble() {}
virtual std::shared_ptr<KeyData> clone() const override
{
virtual std::shared_ptr<KeyData> clone() const override {
return std::make_shared<KeyDataDouble>(d_data, d_unit);
}
virtual void print( std::ostream& os, const std::string& indent = "" ) const override;
virtual void print(std::ostream &os,
const std::string &indent = "") const override;
virtual std::string type() const override { return "double"; }
static std::tuple<double, Units> read(const std::string &);
@ -48,18 +74,16 @@ public:
std::vector<double> d_data;
Units d_unit;
};
class KeyDataBool : public KeyData
{
class KeyDataBool : public KeyData {
public:
KeyDataBool() {}
explicit KeyDataBool(const std::vector<bool> &data) : d_data(data) {}
virtual ~KeyDataBool() {}
virtual std::shared_ptr<KeyData> clone() const override
{
virtual std::shared_ptr<KeyData> clone() const override {
return std::make_shared<KeyDataBool>(d_data);
}
virtual void print( std::ostream& os, const std::string& indent = "" ) const override
{
virtual void print(std::ostream &os,
const std::string &indent = "") const override {
os << indent;
for (size_t i = 0; i < d_data.size(); i++) {
if (i > 0) {
@ -76,18 +100,17 @@ public:
virtual std::string type() const override { return "bool"; }
std::vector<bool> d_data;
};
class KeyDataString : public KeyData
{
class KeyDataString : public KeyData {
public:
KeyDataString() {}
explicit KeyDataString( const std::vector<std::string>& data ) : d_data( data ) {}
explicit KeyDataString(const std::vector<std::string> &data)
: d_data(data) {}
virtual ~KeyDataString() {}
virtual std::shared_ptr<KeyData> clone() const override
{
virtual std::shared_ptr<KeyData> clone() const override {
return std::make_shared<KeyDataString>(d_data);
}
virtual void print( std::ostream& os, const std::string& indent = "" ) const override
{
virtual void print(std::ostream &os,
const std::string &indent = "") const override {
os << indent;
for (size_t i = 0; i < d_data.size(); i++) {
if (i > 0) {
@ -101,30 +124,27 @@ public:
std::vector<std::string> d_data;
};
/********************************************************************
* Get a vector *
********************************************************************/
template <class TYPE>
inline std::vector<TYPE> Database::getVector(
const std::string& key, const std::string& unit ) const
{
inline std::vector<TYPE> Database::getVector(const std::string &key,
const std::string &unit) const {
return getVector<TYPE>(key, Units(unit));
}
template <class TYPE>
inline void Database::putVector(
const std::string& key, const std::vector<TYPE>& data, const std::string& unit )
{
inline void Database::putVector(const std::string &key,
const std::vector<TYPE> &data,
const std::string &unit) {
putVector<TYPE>(key, data, Units(unit));
}
/********************************************************************
* Get a scalar *
********************************************************************/
template <class TYPE>
inline TYPE Database::getScalar( const std::string& key, const Units& unit ) const
{
inline TYPE Database::getScalar(const std::string &key,
const Units &unit) const {
const std::vector<TYPE> &data = getVector<TYPE>(key, unit);
if (data.size() != 1) {
char msg[1000];
@ -134,40 +154,36 @@ inline TYPE Database::getScalar( const std::string& key, const Units& unit ) con
return data[0];
}
template <class TYPE>
inline TYPE Database::getWithDefault(
const std::string& key, const TYPE& value, const Units& unit ) const
{
inline TYPE Database::getWithDefault(const std::string &key, const TYPE &value,
const Units &unit) const {
if (!keyExists(key))
return value;
return getScalar<TYPE>(key, unit);
}
template <class TYPE>
inline void Database::putScalar( const std::string& key, const TYPE& data, const Units& unit )
{
inline void Database::putScalar(const std::string &key, const TYPE &data,
const Units &unit) {
putVector<TYPE>(key, std::vector<TYPE>(1, data), unit);
}
template <class TYPE>
inline TYPE Database::getScalar( const std::string& key, const std::string& unit ) const
{
inline TYPE Database::getScalar(const std::string &key,
const std::string &unit) const {
return getScalar<TYPE>(key, Units(unit));
}
template <class TYPE>
inline TYPE Database::getWithDefault(
const std::string& key, const TYPE& value, const std::string& unit ) const
{
inline TYPE Database::getWithDefault(const std::string &key, const TYPE &value,
const std::string &unit) const {
return getWithDefault<TYPE>(key, value, Units(unit));
}
template <class TYPE>
inline void Database::putScalar( const std::string& key, const TYPE& data, const std::string& unit )
{
inline void Database::putScalar(const std::string &key, const TYPE &data,
const std::string &unit) {
putScalar<TYPE>(key, data, Units(unit));
}
template <class TYPE>
inline void putVector(
const std::string& key, const std::vector<TYPE>& data, const std::string& unit )
{
inline void putVector(const std::string &key, const std::vector<TYPE> &data,
const std::string &unit) {
putVector<TYPE>(key, data, Units(unit));
}
#endif

File diff suppressed because it is too large Load Diff

76
common/Domain.h Executable file → Normal file
View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Domain_INC
#define Domain_INC
@ -21,7 +37,6 @@
* \brief Parallel Domain data structures and helper functions
*/
/**
* \class Box
*
@ -102,9 +117,7 @@ public:
*/
inline const std::vector<Patch> &getAllPatch() const { return d_patches; }
private:
/**
* \brief initialize from database
*/
@ -115,9 +128,7 @@ private:
Patch *d_localPatch;
std::vector<Patch> d_patches;
public: // Public variables (need to create accessors instead)
std::shared_ptr<Database> database;
double Lx, Ly, Lz, Volume, voxel_length;
int Nx, Ny, Nz, N;
@ -170,10 +181,18 @@ public: // Public variables (need to create accessors instead)
// Get the actual D3Q19 communication counts (based on location of solid phase)
// Discrete velocity set symmetry implies the sendcount = recvcount
//......................................................................................
inline int recvCount( const char* dir ) const { return getRecvList( dir ).size(); }
inline int sendCount( const char* dir ) const { return getSendList( dir ).size(); }
inline const int* recvList( const char* dir ) const { return getRecvList( dir ).data(); }
inline const int* sendList( const char* dir ) const { return getSendList( dir ).data(); }
inline int recvCount(const char *dir) const {
return getRecvList(dir).size();
}
inline int sendCount(const char *dir) const {
return getSendList(dir).size();
}
inline const int *recvList(const char *dir) const {
return getRecvList(dir).data();
}
inline const int *sendList(const char *dir) const {
return getSendList(dir).data();
}
//......................................................................................
// Solid indicator function
@ -218,7 +237,8 @@ public: // Public variables (need to create accessors instead)
* @param Datatype - data type to use
* @param UserData - Array to store the values that are read
*/
void ReadFromFile(const std::string& Filename,const std::string& Datatype, double *UserData);
void ReadFromFile(const std::string &Filename, const std::string &Datatype,
double *UserData);
/**
* \brief Aggregate labels from all MPI processes and write to a file
@ -233,7 +253,6 @@ public: // Public variables (need to create accessors instead)
void AggregateLabels(const std::string &filename, DoubleArray &UserData);
private:
/**
* \brief Pack halo data for 8-bit integer
* @param list - list of values in the halo
@ -255,25 +274,28 @@ private:
//......................................................................................
MPI_Request req1[18], req2[18];
//......................................................................................
std::vector<int> sendList_x, sendList_y, sendList_z, sendList_X, sendList_Y, sendList_Z;
std::vector<int> sendList_xy, sendList_yz, sendList_xz, sendList_Xy, sendList_Yz, sendList_xZ;
std::vector<int> sendList_xY, sendList_yZ, sendList_Xz, sendList_XY, sendList_YZ, sendList_XZ;
std::vector<int> sendList_x, sendList_y, sendList_z, sendList_X, sendList_Y,
sendList_Z;
std::vector<int> sendList_xy, sendList_yz, sendList_xz, sendList_Xy,
sendList_Yz, sendList_xZ;
std::vector<int> sendList_xY, sendList_yZ, sendList_Xz, sendList_XY,
sendList_YZ, sendList_XZ;
//......................................................................................
std::vector<int> recvList_x, recvList_y, recvList_z, recvList_X, recvList_Y, recvList_Z;
std::vector<int> recvList_xy, recvList_yz, recvList_xz, recvList_Xy, recvList_Yz, recvList_xZ;
std::vector<int> recvList_xY, recvList_yZ, recvList_Xz, recvList_XY, recvList_YZ, recvList_XZ;
std::vector<int> recvList_x, recvList_y, recvList_z, recvList_X, recvList_Y,
recvList_Z;
std::vector<int> recvList_xy, recvList_yz, recvList_xz, recvList_Xy,
recvList_Yz, recvList_xZ;
std::vector<int> recvList_xY, recvList_yZ, recvList_Xz, recvList_XY,
recvList_YZ, recvList_XZ;
//......................................................................................
const std::vector<int> &getRecvList(const char *dir) const;
const std::vector<int> &getSendList(const char *dir) const;
};
template <class TYPE> class PatchData;
enum class DataLocation { CPU, DEVICE };
/**
* \class Patch
*
@ -282,7 +304,6 @@ enum class DataLocation { CPU, DEVICE };
*/
class Patch {
public:
//! Empty constructor
Patch() = delete;
@ -297,21 +318,18 @@ public:
//! Create patch data
template <class TYPE>
std::shared_ptr<PatchData<TYPE>> createPatchData( DataLocation location ) const;
std::shared_ptr<PatchData<TYPE>>
createPatchData(DataLocation location) const;
private:
Box d_box;
int d_owner;
Domain *d_domain;
};
// Class to hold data on a patch
template<class TYPE>
class PatchData {
template <class TYPE> class PatchData {
public:
//! Get the raw data pointer
TYPE *data() { return d_data; }
@ -338,10 +356,10 @@ private:
const Patch *d_patch;
TYPE *d_data;
TYPE *d_gcw;
};
void WriteCheckpoint(const char *FILENAME, const double *cDen, const double *cfq, size_t Np);
void WriteCheckpoint(const char *FILENAME, const double *cDen,
const double *cfq, size_t Np);
void ReadCheckpoint(char *FILENAME, double *cDen, double *cfq, size_t Np);

View File

@ -1,6 +1,5 @@
#include "FunctionTable.hpp"
/********************************************************
* Random number generation *
********************************************************/
@ -94,54 +93,35 @@ template<> long double genRand<long double>()
* axpy *
********************************************************/
template <>
void call_axpy<float>( size_t N, const float alpha, const float *x, float *y )
{
void call_axpy<float>(size_t N, const float alpha, const float *x, float *y) {
ERROR("Not finished");
}
template <>
void call_axpy<double>( size_t N, const double alpha, const double *x, double *y )
{
void call_axpy<double>(size_t N, const double alpha, const double *x,
double *y) {
ERROR("Not finished");
}
/********************************************************
* Multiply two arrays *
********************************************************/
template <>
void call_gemv<double>(
size_t M, size_t N, double alpha, double beta, const double *A, const double *x, double *y )
{
void call_gemv<double>(size_t M, size_t N, double alpha, double beta,
const double *A, const double *x, double *y) {
ERROR("Not finished");
}
template <>
void call_gemv<float>(
size_t M, size_t N, float alpha, float beta, const float *A, const float *x, float *y )
{
void call_gemv<float>(size_t M, size_t N, float alpha, float beta,
const float *A, const float *x, float *y) {
ERROR("Not finished");
}
template <>
void call_gemm<double>( size_t M,
size_t N,
size_t K,
double alpha,
double beta,
const double *A,
const double *B,
double *C )
{
void call_gemm<double>(size_t M, size_t N, size_t K, double alpha, double beta,
const double *A, const double *B, double *C) {
ERROR("Not finished");
}
template <>
void call_gemm<float>( size_t M,
size_t N,
size_t K,
float alpha,
float beta,
const float *A,
const float *B,
float *C )
{
void call_gemm<float>(size_t M, size_t N, size_t K, float alpha, float beta,
const float *A, const float *B, float *C) {
ERROR("Not finished");
}

View File

@ -1,28 +1,39 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_FunctionTable
#define included_FunctionTable
#include "common/ArraySize.h"
#include <functional>
/*!
* Class FunctionTable is a serial function table class that defines
* a series of operations that can be performed on the Array class.
* Users can impliment additional versions of the function table that match
* the interface to change the behavior of the array class.
*/
class FunctionTable final
{
class FunctionTable final {
public:
/*!
* Initialize the array with random values
* @param[in] x The array to operate on
*/
template<class TYPE, class FUN>
static void rand( Array<TYPE, FUN> &x );
template <class TYPE, class FUN> static void rand(Array<TYPE, FUN> &x);
/*!
* Perform a reduce operator y = f(x)
@ -34,7 +45,8 @@ public:
* @return The reduction
*/
template <class TYPE, class FUN, typename LAMBDA>
static inline TYPE reduce( LAMBDA &op, const Array<TYPE, FUN> &A, const TYPE &initialValue );
static inline TYPE reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const TYPE &initialValue);
/*!
* Perform a reduce operator z = f(x,y)
@ -47,8 +59,7 @@ public:
* @return The reduction
*/
template <class TYPE, class FUN, typename LAMBDA>
static inline TYPE reduce( LAMBDA &op,
const Array<TYPE, FUN> &A,
static inline TYPE reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &B,
const TYPE &initialValue);
@ -60,7 +71,8 @@ public:
* @param[out] y The output array
*/
template <class TYPE, class FUN, typename LAMBDA>
static inline void transform( LAMBDA &fun, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y );
static inline void transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
Array<TYPE, FUN> &y);
/*!
* Perform a element-wise operation z = f(x,y)
@ -71,8 +83,7 @@ public:
* @param[out] z The output array
*/
template <class TYPE, class FUN, typename LAMBDA>
static inline void transform( LAMBDA &fun,
const Array<TYPE, FUN> &x,
static inline void transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
const Array<TYPE, FUN> &y,
Array<TYPE, FUN> &z);
@ -83,8 +94,8 @@ public:
* @param[out] c The output array
*/
template <class TYPE, class FUN>
static void
multiply( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, Array<TYPE, FUN> &c );
static void multiply(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
Array<TYPE, FUN> &c);
/*!
* Perform dgemv/dgemm equavalent operation ( C = alpha*A*B + beta*C )
@ -95,10 +106,8 @@ public:
* @param[in,out] C The output array C
*/
template <class TYPE, class FUN>
static void gemm( const TYPE alpha,
const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &B,
const TYPE beta,
static void gemm(const TYPE alpha, const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &B, const TYPE beta,
Array<TYPE, FUN> &C);
/*!
@ -108,7 +117,8 @@ public:
* @param[in,out] y The output array y
*/
template <class TYPE, class FUN>
static void axpy( const TYPE alpha, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y );
static void axpy(const TYPE alpha, const Array<TYPE, FUN> &x,
Array<TYPE, FUN> &y);
/*!
* Check if two arrays are approximately equal
@ -117,24 +127,15 @@ public:
* @param[in] tol The tolerance
*/
template <class TYPE, class FUN>
static bool equals( const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B, TYPE tol );
static bool equals(const Array<TYPE, FUN> &A, const Array<TYPE, FUN> &B,
TYPE tol);
template <class TYPE>
static inline void gemmWrapper( char TRANSA,
char TRANSB,
int M,
int N,
int K,
TYPE alpha,
const TYPE *A,
int LDA,
const TYPE *B,
int LDB,
TYPE beta,
TYPE *C,
static inline void gemmWrapper(char TRANSA, char TRANSB, int M, int N,
int K, TYPE alpha, const TYPE *A, int LDA,
const TYPE *B, int LDB, TYPE beta, TYPE *C,
int LDC);
/* Specialized Functions */
/*!
@ -143,7 +144,8 @@ public:
* @param[out] B The output array
*/
template <class TYPE, class FUN, class ALLOC>
static void transformReLU( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B );
static void transformReLU(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*!
* Perform a element-wise operation B = |A|
@ -151,7 +153,8 @@ public:
* @param[out] B The output array
*/
template <class TYPE, class FUN, class ALLOC>
static void transformAbs( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B );
static void transformAbs(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*!
* Perform a element-wise operation B = tanh(A)
@ -159,7 +162,8 @@ public:
* @param[out] B The output array
*/
template <class TYPE, class FUN, class ALLOC>
static void transformTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B );
static void transformTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*!
* Perform a element-wise operation B = max(-1 , min(1 , A) )
@ -167,7 +171,8 @@ public:
* @param[out] B The output array
*/
template <class TYPE, class FUN, class ALLOC>
static void transformHardTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B );
static void transformHardTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*!
* Perform a element-wise operation B = 1 / (1 + exp(-A))
@ -175,7 +180,8 @@ public:
* @param[out] B The output array
*/
template <class TYPE, class FUN, class ALLOC>
static void transformSigmoid( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B );
static void transformSigmoid(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*!
* Perform a element-wise operation B = log(exp(A) + 1)
@ -183,7 +189,8 @@ public:
* @param[out] B The output array
*/
template <class TYPE, class FUN, class ALLOC>
static void transformSoftPlus( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B );
static void transformSoftPlus(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B);
/*!
* Sum the elements of the Array
@ -195,9 +202,7 @@ public:
private:
FunctionTable();
template<class T>
static inline void rand( size_t N, T *x );
template <class T> static inline void rand(size_t N, T *x);
};
#endif

View File

@ -1,3 +1,35 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_FunctionTable_hpp
#define included_FunctionTable_hpp
@ -9,7 +41,6 @@
#include <limits>
//#include <random>
/********************************************************
* Random number initialization *
********************************************************/
@ -26,8 +57,8 @@ inline void FunctionTable::rand( Array<TYPE, FUN> &x )
* Reduction *
********************************************************/
template <class TYPE, class FUN, typename LAMBDA>
inline TYPE FunctionTable::reduce( LAMBDA &op, const Array<TYPE, FUN> &A, const TYPE &initialValue )
{
inline TYPE FunctionTable::reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const TYPE &initialValue) {
if (A.length() == 0)
return TYPE();
const TYPE *x = A.data();
@ -37,11 +68,9 @@ inline TYPE FunctionTable::reduce( LAMBDA &op, const Array<TYPE, FUN> &A, const
return y;
}
template <class TYPE, class FUN, typename LAMBDA>
inline TYPE FunctionTable::reduce( LAMBDA &op,
const Array<TYPE, FUN> &A,
inline TYPE FunctionTable::reduce(LAMBDA &op, const Array<TYPE, FUN> &A,
const Array<TYPE, FUN> &B,
const TYPE &initialValue )
{
const TYPE &initialValue) {
ARRAY_ASSERT(A.length() == B.length());
if (A.length() == 0)
return TYPE();
@ -53,24 +82,21 @@ inline TYPE FunctionTable::reduce( LAMBDA &op,
return z;
}
/********************************************************
* Unary transformation *
********************************************************/
template <class TYPE, class FUN, typename LAMBDA>
inline void FunctionTable::transform( LAMBDA &fun, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y )
{
inline void FunctionTable::transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
Array<TYPE, FUN> &y) {
y.resize(x.size());
const size_t N = x.length();
for (size_t i = 0; i < N; i++)
y(i) = fun(x(i));
}
template <class TYPE, class FUN, typename LAMBDA>
inline void FunctionTable::transform( LAMBDA &fun,
const Array<TYPE, FUN> &x,
inline void FunctionTable::transform(LAMBDA &fun, const Array<TYPE, FUN> &x,
const Array<TYPE, FUN> &y,
Array<TYPE, FUN> &z )
{
Array<TYPE, FUN> &z) {
if (x.size() != y.size())
throw std::logic_error("Sizes of x and y do not match");
z.resize(x.size());
@ -79,7 +105,6 @@ inline void FunctionTable::transform( LAMBDA &fun,
z(i) = fun(x(i), y(i));
}
/********************************************************
* axpy *
********************************************************/
@ -88,36 +113,36 @@ void call_axpy( size_t N, const TYPE alpha, const TYPE *x, TYPE *y );
template <>
void call_axpy<float>(size_t N, const float alpha, const float *x, float *y);
template <>
void call_axpy<double>( size_t N, const double alpha, const double *x, double *y );
void call_axpy<double>(size_t N, const double alpha, const double *x,
double *y);
template <class TYPE>
void call_axpy( size_t N, const TYPE alpha, const TYPE *x, TYPE *y )
{
void call_axpy(size_t N, const TYPE alpha, const TYPE *x, TYPE *y) {
for (size_t i = 0; i < N; i++)
y[i] += alpha * x[i];
}
template <class TYPE, class FUN>
void FunctionTable::axpy( const TYPE alpha, const Array<TYPE, FUN> &x, Array<TYPE, FUN> &y )
{
void FunctionTable::axpy(const TYPE alpha, const Array<TYPE, FUN> &x,
Array<TYPE, FUN> &y) {
if (x.size() != y.size())
throw std::logic_error("Array sizes do not match");
call_axpy(x.length(), alpha, x.data(), y.data());
}
/********************************************************
* Multiply two arrays *
********************************************************/
template <class TYPE>
void call_gemv( size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *x, TYPE *y );
void call_gemv(size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A,
const TYPE *x, TYPE *y);
template <>
void call_gemv<double>(
size_t M, size_t N, double alpha, double beta, const double *A, const double *x, double *y );
void call_gemv<double>(size_t M, size_t N, double alpha, double beta,
const double *A, const double *x, double *y);
template <>
void call_gemv<float>(
size_t M, size_t N, float alpha, float beta, const float *A, const float *x, float *y );
void call_gemv<float>(size_t M, size_t N, float alpha, float beta,
const float *A, const float *x, float *y);
template <class TYPE>
void call_gemv( size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *x, TYPE *y )
{
void call_gemv(size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A,
const TYPE *x, TYPE *y) {
for (size_t i = 0; i < M; i++)
y[i] = beta * y[i];
for (size_t j = 0; j < N; j++) {
@ -126,30 +151,17 @@ void call_gemv( size_t M, size_t N, TYPE alpha, TYPE beta, const TYPE *A, const
}
}
template <class TYPE>
void call_gemm(
size_t M, size_t N, size_t K, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *B, TYPE *C );
void call_gemm(size_t M, size_t N, size_t K, TYPE alpha, TYPE beta,
const TYPE *A, const TYPE *B, TYPE *C);
template <>
void call_gemm<double>( size_t M,
size_t N,
size_t K,
double alpha,
double beta,
const double *A,
const double *B,
double *C );
void call_gemm<double>(size_t M, size_t N, size_t K, double alpha, double beta,
const double *A, const double *B, double *C);
template <>
void call_gemm<float>( size_t M,
size_t N,
size_t K,
float alpha,
float beta,
const float *A,
const float *B,
float *C );
void call_gemm<float>(size_t M, size_t N, size_t K, float alpha, float beta,
const float *A, const float *B, float *C);
template <class TYPE>
void call_gemm(
size_t M, size_t N, size_t K, TYPE alpha, TYPE beta, const TYPE *A, const TYPE *B, TYPE *C )
{
void call_gemm(size_t M, size_t N, size_t K, TYPE alpha, TYPE beta,
const TYPE *A, const TYPE *B, TYPE *C) {
for (size_t i = 0; i < K * M; i++)
C[i] = beta * C[i];
for (size_t k = 0; k < K; k++) {
@ -160,50 +172,46 @@ void call_gemm(
}
}
template <class TYPE, class FUN>
void FunctionTable::gemm( const TYPE alpha,
const Array<TYPE, FUN> &a,
const Array<TYPE, FUN> &b,
const TYPE beta,
Array<TYPE, FUN> &c )
{
void FunctionTable::gemm(const TYPE alpha, const Array<TYPE, FUN> &a,
const Array<TYPE, FUN> &b, const TYPE beta,
Array<TYPE, FUN> &c) {
if (a.size(1) != b.size(0))
throw std::logic_error("Inner dimensions must match");
if (a.ndim() == 2 && b.ndim() == 1) {
call_gemv<TYPE>( a.size( 0 ), a.size( 1 ), alpha, beta, a.data(), b.data(), c.data() );
call_gemv<TYPE>(a.size(0), a.size(1), alpha, beta, a.data(), b.data(),
c.data());
} else if (a.ndim() <= 2 && b.ndim() <= 2) {
call_gemm<TYPE>(
a.size( 0 ), a.size( 1 ), b.size( 1 ), alpha, beta, a.data(), b.data(), c.data() );
call_gemm<TYPE>(a.size(0), a.size(1), b.size(1), alpha, beta, a.data(),
b.data(), c.data());
} else {
throw std::logic_error("Not finished yet");
}
}
template <class TYPE, class FUN>
void FunctionTable::multiply(const Array<TYPE, FUN> &a,
const Array<TYPE, FUN> &b,
Array<TYPE, FUN> &c )
{
const Array<TYPE, FUN> &b, Array<TYPE, FUN> &c) {
if (a.size(1) != b.size(0))
throw std::logic_error("Inner dimensions must match");
if (a.ndim() == 2 && b.ndim() == 1) {
c.resize(a.size(0));
call_gemv<TYPE>( a.size( 0 ), a.size( 1 ), 1, 0, a.data(), b.data(), c.data() );
call_gemv<TYPE>(a.size(0), a.size(1), 1, 0, a.data(), b.data(),
c.data());
} else if (a.ndim() <= 2 && b.ndim() <= 2) {
c.resize(a.size(0), b.size(1));
call_gemm<TYPE>(
a.size( 0 ), a.size( 1 ), b.size( 1 ), 1, 0, a.data(), b.data(), c.data() );
call_gemm<TYPE>(a.size(0), a.size(1), b.size(1), 1, 0, a.data(),
b.data(), c.data());
} else {
throw std::logic_error("Not finished yet");
}
}
/********************************************************
* Check if two arrays are equal *
********************************************************/
template <class TYPE, class FUN>
inline typename std::enable_if<std::is_integral<TYPE>::value, bool>::type
FunctionTableCompare( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE )
{
FunctionTableCompare(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
TYPE) {
bool pass = true;
if (a.size() != b.size())
throw std::logic_error("Sizes of x and y do not match");
@ -213,8 +221,8 @@ FunctionTableCompare( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE
}
template <class TYPE, class FUN>
inline typename std::enable_if<std::is_floating_point<TYPE>::value, bool>::type
FunctionTableCompare( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE tol )
{
FunctionTableCompare(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
TYPE tol) {
bool pass = true;
if (a.size() != b.size())
throw std::logic_error("Sizes of x and y do not match");
@ -223,32 +231,33 @@ FunctionTableCompare( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE
return pass;
}
template <class TYPE, class FUN>
bool FunctionTable::equals( const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b, TYPE tol )
{
bool FunctionTable::equals(const Array<TYPE, FUN> &a, const Array<TYPE, FUN> &b,
TYPE tol) {
return FunctionTableCompare(a, b, tol);
}
/********************************************************
* Specialized Functions *
********************************************************/
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformReLU( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B )
{
const auto &fun = []( const TYPE &a ) { return std::max( a, static_cast<TYPE>( 0 ) ); };
void FunctionTable::transformReLU(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B) {
const auto &fun = [](const TYPE &a) {
return std::max(a, static_cast<TYPE>(0));
};
transform(fun, A, B);
}
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformAbs( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B )
{
void FunctionTable::transformAbs(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B) {
B.resize(A.size());
const auto &fun = [](const TYPE &a) { return std::abs(a); };
transform(fun, A, B);
}
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B )
{
void FunctionTable::transformTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B) {
B.resize(A.size());
const auto &fun = [](const TYPE &a) { return tanh(a); };
transform(fun, A, B);
@ -256,18 +265,18 @@ void FunctionTable::transformTanh( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE,
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformHardTanh(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B )
{
Array<TYPE, FUN, ALLOC> &B) {
B.resize(A.size());
const auto &fun = [](const TYPE &a) {
return std::max( -static_cast<TYPE>( 1.0 ), std::min( static_cast<TYPE>( 1.0 ), a ) );
return std::max(-static_cast<TYPE>(1.0),
std::min(static_cast<TYPE>(1.0), a));
};
transform(fun, A, B);
}
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformSigmoid( const Array<TYPE, FUN, ALLOC> &A, Array<TYPE, FUN, ALLOC> &B )
{
void FunctionTable::transformSigmoid(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B) {
B.resize(A.size());
const auto &fun = [](const TYPE &a) { return 1.0 / (1.0 + exp(-a)); };
transform(fun, A, B);
@ -275,37 +284,24 @@ void FunctionTable::transformSigmoid( const Array<TYPE, FUN, ALLOC> &A, Array<TY
template <class TYPE, class FUN, class ALLOC>
void FunctionTable::transformSoftPlus(const Array<TYPE, FUN, ALLOC> &A,
Array<TYPE, FUN, ALLOC> &B )
{
Array<TYPE, FUN, ALLOC> &B) {
B.resize(A.size());
const auto &fun = [](const TYPE &a) { return log1p(exp(a)); };
transform(fun, A, B);
}
template <class TYPE, class FUN, class ALLOC>
TYPE FunctionTable::sum( const Array<TYPE, FUN, ALLOC> &A )
{
TYPE FunctionTable::sum(const Array<TYPE, FUN, ALLOC> &A) {
const auto &fun = [](const TYPE &a, const TYPE &b) { return a + b; };
return reduce(fun, A, (TYPE)0);
}
template <class TYPE>
inline void FunctionTable::gemmWrapper( char TRANSA,
char TRANSB,
int M,
int N,
int K,
TYPE alpha,
const TYPE *A,
int LDA,
const TYPE *B,
int LDB,
TYPE beta,
TYPE *C,
int LDC )
{
inline void FunctionTable::gemmWrapper(char TRANSA, char TRANSB, int M, int N,
int K, TYPE alpha, const TYPE *A,
int LDA, const TYPE *B, int LDB,
TYPE beta, TYPE *C, int LDC) {
ERROR("Not finished");
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,6 @@ redistribution is prohibited.
#ifndef included_LBPM_MPI
#define included_LBPM_MPI
#include <array>
#include <atomic>
#include <complex>
@ -31,7 +30,6 @@ redistribution is prohibited.
#include <string>
#include <vector>
// Include mpi.h (or define MPI objects)
// clang-format off
#ifdef USE_MPI
@ -48,10 +46,8 @@ redistribution is prohibited.
#endif
// clang-format on
namespace Utilities {
/**
* \class MPI
*
@ -69,8 +65,7 @@ namespace Utilities {
* succeed provided that the size of the data type object is a fixed size on
* all processors. sizeof(type) must be the same for all elements and processors.
*/
class MPI final
{
class MPI final {
public:
enum class ThreadSupport : int { SINGLE, FUNNELED, SERIALIZED, MULTIPLE };
@ -87,11 +82,9 @@ public: // Constructors
*/
MPI();
//! Empty destructor
~MPI();
/**
* \brief Constructor from existing MPI communicator
* \details This constructor creates a new communicator from an existing MPI communicator.
@ -106,7 +99,6 @@ public: // Constructors
*/
MPI(MPI_Comm comm, bool manage = false);
/**
* \brief Constructor from existing communicator
* \details This constructor creates a new communicator from an existing communicator.
@ -115,14 +107,12 @@ public: // Constructors
*/
MPI(const MPI &comm);
/*!
* Move constructor
* @param rhs Communicator to copy
*/
MPI(MPI &&rhs);
/**
* \brief Assignment operator
* \details This operator overloads the assignment to correctly copy an communicator
@ -130,21 +120,18 @@ public: // Constructors
*/
MPI &operator=(const MPI &comm);
/*!
* Move assignment operator
* @param rhs Communicator to copy
*/
MPI &operator=(MPI &&rhs);
/**
* \brief Reset the object
* \details This resets the object to the empty state without an MPI_Comm
*/
void reset();
public: // Member functions
/**
* \brief Get the node name
@ -153,19 +140,15 @@ public: // Member functions
*/
static std::string getNodeName();
//! Function to return the number of processors available
static int getNumberOfProcessors();
//! Function to return the affinity of the current process
static std::vector<int> getProcessAffinity();
//! Function to set the affinity of the current process
static void setProcessAffinity(const std::vector<int> &procs);
/**
* \brief Load balance the processes within a node
* \details This function will redistribute the processes within a node using the
@ -189,22 +172,21 @@ public: // Member functions
* processors).
*
*/
static void balanceProcesses( const MPI &comm = MPI( MPI_COMM_WORLD ), const int method = 1,
const std::vector<int> &procs = std::vector<int>(), const int N_min = 1,
const int N_max = -1 );
static void
balanceProcesses(const MPI &comm = MPI(MPI_COMM_WORLD),
const int method = 1,
const std::vector<int> &procs = std::vector<int>(),
const int N_min = 1, const int N_max = -1);
//! Query the level of thread support
static ThreadSupport queryThreadSupport();
/**
* \brief Generate a random number
* \details This generates a random number that is consistent across the comm
*/
size_t rand() const;
/**
* \brief Split an existing communicator
* \details This creates a new communicator by splitting an existing communicator.
@ -224,7 +206,6 @@ public: // Member functions
*/
MPI split(int color, int key = -1) const;
/**
* \brief Split an existing communicator by node
* \details This creates a new communicator by splitting an existing communicator
@ -242,7 +223,6 @@ public: // Member functions
*/
MPI splitByNode(int key = -1) const;
/**
* \brief Duplicate an existing communicator
* \details This creates a new communicator by duplicating an existing communicator.
@ -253,7 +233,6 @@ public: // Member functions
*/
MPI dup() const;
/**
* \brief Create a communicator from the intersection of two communicators
* \details This creates a new communicator by intersecting two existing communicators.
@ -267,13 +246,11 @@ public: // Member functions
*/
static MPI intersect(const MPI &comm1, const MPI &comm2);
/**
* Check if the current communicator is NULL
*/
bool isNull() const { return d_isNull; }
/**
* \brief Return the global ranks for the comm
* \details This returns a vector which contains the global ranks for each
@ -283,7 +260,6 @@ public: // Member functions
*/
std::vector<int> globalRanks() const;
/**
* Get the current MPI communicator.
* Note: The underlying MPI_Comm object may be free'd by the object when it is no
@ -294,7 +270,6 @@ public: // Member functions
*/
const MPI_Comm &getCommunicator() const { return communicator; }
/**
* \brief Overload operator ==
* \details Overload operator comm1 == comm2. Two MPI objects are == if they share the same
@ -303,7 +278,6 @@ public: // Member functions
*/
bool operator==(const MPI &) const;
/**
* \brief Overload operator !=
* \details Overload operator comm1 != comm2. Two MPI objects are != if they
@ -312,7 +286,6 @@ public: // Member functions
*/
bool operator!=(const MPI &) const;
/**
* \brief Overload operator <
* \details Overload operator comm1 < comm2. One MPI object is < another iff all the
@ -326,7 +299,6 @@ public: // Member functions
*/
bool operator<(const MPI &) const;
/**
* \brief Overload operator <=
* \details Overload operator comm1 <= comm2. One MPI object is <= another iff all the
@ -339,7 +311,6 @@ public: // Member functions
*/
bool operator<=(const MPI &) const;
/**
* \brief Overload operator >
* \details Overload operator comm1 > comm2. One MPI object is > another iff all the
@ -353,7 +324,6 @@ public: // Member functions
*/
bool operator>(const MPI &) const;
/**
* \brief Overload operator >=
* \details Overload operator comm1 >= comm2. One MPI object is > another iff all the
@ -367,7 +337,6 @@ public: // Member functions
*/
bool operator>=(const MPI &) const;
/**
* \brief Compare to another communicator
* \details This compares the current communicator to another communicator.
@ -378,26 +347,22 @@ public: // Member functions
*/
int compare(const MPI &) const;
/**
* Return the processor rank (identifier) from 0 through the number of
* processors minus one.
*/
int getRank() const { return comm_rank; }
/**
* Return the number of processors.
*/
int getSize() const { return comm_size; }
/**
* Return the maximum tag
*/
int maxTag() const { return d_maxTag; }
/**
* \brief Return a new tag
* \details This routine will return an unused tag for communication.
@ -406,7 +371,6 @@ public: // Member functions
*/
int newTag();
/**
* Call MPI_Abort or exit depending on whether running with one or more
* processes and value set by function above, if called. The default is
@ -416,7 +380,6 @@ public: // Member functions
*/
void abort() const;
/**
* Set boolean flag indicating whether exit or abort is called when running
* with one processor. Calling this function influences the behavior of
@ -425,7 +388,6 @@ public: // Member functions
*/
void setCallAbortInSerialInsteadOfExit(bool flag = true);
/**
* \brief Boolean all reduce
* \details This function performs a boolean all reduce across all processors.
@ -434,7 +396,6 @@ public: // Member functions
*/
bool allReduce(const bool value) const;
/**
* \brief Boolean any reduce
* \details This function performs a boolean any reduce across all processors.
@ -443,16 +404,13 @@ public: // Member functions
*/
bool anyReduce(const bool value) const;
/**
* \brief Sum Reduce
* \details This function performs a sum all reduce across all processor.
* It returns the sum across all processors;
* \param value The input value for the all reduce
*/
template<class type>
type sumReduce( const type value ) const;
template <class type> type sumReduce(const type value) const;
/**
* \brief Sum Reduce
@ -462,9 +420,7 @@ public: // Member functions
* \param x The input/output array for the reduce
* \param n The number of values in the array (must match on all nodes)
*/
template<class type>
void sumReduce( type *x, const int n = 1 ) const;
template <class type> void sumReduce(type *x, const int n = 1) const;
/**
* \brief Sum Reduce
@ -478,16 +434,13 @@ public: // Member functions
template <class type>
void sumReduce(const type *x, type *y, const int n = 1) const;
/**
* \brief Min Reduce
* \details This function performs a min all reduce across all processor.
* It returns the minimum value across all processors;
* \param value The input value for the all reduce
*/
template<class type>
type minReduce( const type value ) const;
template <class type> type minReduce(const type value) const;
/**
* \brief Sum Reduce
@ -506,7 +459,6 @@ public: // Member functions
template <class type>
void minReduce(type *x, const int n = 1, int *rank_of_min = nullptr) const;
/**
* \brief Sum Reduce
* \details Perform an array min Reduce across all nodes. Each
@ -523,8 +475,8 @@ public: // Member functions
* minimum value
*/
template <class type>
void minReduce( const type *x, type *y, const int n = 1, int *rank_of_min = nullptr ) const;
void minReduce(const type *x, type *y, const int n = 1,
int *rank_of_min = nullptr) const;
/**
* \brief Max Reduce
@ -532,9 +484,7 @@ public: // Member functions
* It returns the maximum value across all processors;
* \param value The input value for the all reduce
*/
template<class type>
type maxReduce( const type value ) const;
template <class type> type maxReduce(const type value) const;
/**
* \brief Sum Reduce
@ -553,7 +503,6 @@ public: // Member functions
template <class type>
void maxReduce(type *x, const int n = 1, int *rank_of_max = nullptr) const;
/**
* \brief Sum Reduce
* \details Perform an array max Reduce across all nodes. Each
@ -570,8 +519,8 @@ public: // Member functions
* minimum value
*/
template <class type>
void maxReduce( const type *x, type *y, const int n = 1, int *rank_of_max = nullptr ) const;
void maxReduce(const type *x, type *y, const int n = 1,
int *rank_of_max = nullptr) const;
/**
* \brief Scan Sum Reduce
@ -584,7 +533,6 @@ public: // Member functions
template <class type>
void sumScan(const type *x, type *y, const int n = 1) const;
/**
* \brief Scan Min Reduce
* \details Computes the min scan (partial reductions) of data on a collection of processes.
@ -596,7 +544,6 @@ public: // Member functions
template <class type>
void minScan(const type *x, type *y, const int n = 1) const;
/**
* \brief Scan Max Reduce
* \details Computes the max scan (partial reductions) of data on a collection of processes.
@ -608,16 +555,13 @@ public: // Member functions
template <class type>
void maxScan(const type *x, type *y, const int n = 1) const;
/**
* \brief Broadcast
* \details This function broadcasts a value from root to all processors
* \param value The input value for the broadcast.
* \param root The processor performing the broadcast
*/
template<class type>
type bcast( const type &value, const int root ) const;
template <class type> type bcast(const type &value, const int root) const;
/**
* \brief Broadcast
@ -629,13 +573,11 @@ public: // Member functions
template <class type>
void bcast(type *value, const int n, const int root) const;
/**
* Perform a global barrier across all processors.
*/
void barrier() const;
/*!
* @brief This function sends an MPI message with an array to another processor.
*
@ -653,8 +595,8 @@ public: // Member functions
* The matching recv must share this tag.
*/
template <class type>
void send( const type *buf, const int length, const int recv, int tag = 0 ) const;
void send(const type *buf, const int length, const int recv,
int tag = 0) const;
/*!
* @brief This function sends an MPI message with an array of bytes
@ -669,8 +611,8 @@ public: // Member functions
* to be sent with this message. Default tag is 0.
* The matching recv must share this tag.
*/
void sendBytes( const void *buf, const int N_bytes, const int recv, int tag = 0 ) const;
void sendBytes(const void *buf, const int N_bytes, const int recv,
int tag = 0) const;
/*!
* @brief This function sends an MPI message with an array
@ -685,9 +627,8 @@ public: // Member functions
* to be sent with this message.
*/
template <class type>
MPI_Request Isend(
const type *buf, const int length, const int recv_proc, const int tag ) const;
MPI_Request Isend(const type *buf, const int length, const int recv_proc,
const int tag) const;
/*!
* @brief This function sends an MPI message with an array of bytes
@ -701,9 +642,8 @@ public: // Member functions
* @param tag Integer argument specifying an integer tag
* to be sent with this message.
*/
MPI_Request IsendBytes(
const void *buf, const int N_bytes, const int recv_proc, const int tag ) const;
MPI_Request IsendBytes(const void *buf, const int N_bytes,
const int recv_proc, const int tag) const;
/*!
* @brief This function receives an MPI message with a data
@ -722,13 +662,11 @@ public: // Member functions
* by the tag of the incoming message. Default tag is 0.
*/
template <class type>
inline void recv( type *buf, int length, const int send, int tag ) const
{
inline void recv(type *buf, int length, const int send, int tag) const {
int length2 = length;
recv(buf, length2, send, false, tag);
}
/*!
* @brief This function receives an MPI message with a data
* array from another processor.
@ -749,8 +687,8 @@ public: // Member functions
* by the tag of the incoming message. Default tag is 0.
*/
template <class type>
void recv( type *buf, int &length, const int send, const bool get_length, int tag ) const;
void recv(type *buf, int &length, const int send, const bool get_length,
int tag) const;
/*!
* @brief This function receives an MPI message with an array of
@ -767,7 +705,6 @@ public: // Member functions
*/
void recvBytes(void *buf, int &N_bytes, const int send, int tag = 0) const;
/*!
* @brief This function receives an MPI message with a data
* array from another processor using a non-blocking call.
@ -779,8 +716,8 @@ public: // Member functions
* be matched by the tag of the incoming message.
*/
template <class type>
MPI_Request Irecv( type *buf, const int length, const int send_proc, const int tag ) const;
MPI_Request Irecv(type *buf, const int length, const int send_proc,
const int tag) const;
/*!
* @brief This function receives an MPI message with an array of
@ -794,26 +731,22 @@ public: // Member functions
* @param tag Integer argument specifying a tag which must
* be matched by the tag of the incoming message.
*/
MPI_Request IrecvBytes(
void *buf, const int N_bytes, const int send_proc, const int tag ) const;
MPI_Request IrecvBytes(void *buf, const int N_bytes, const int send_proc,
const int tag) const;
/*!
* @brief This function sends and recieves data using a blocking call
*/
template <class type>
void sendrecv( const type *sendbuf, int sendcount, int dest, int sendtag, type *recvbuf,
int recvcount, int source, int recvtag ) const;
void sendrecv(const type *sendbuf, int sendcount, int dest, int sendtag,
type *recvbuf, int recvcount, int source, int recvtag) const;
/*!
* Each processor sends every other processor a single value.
* @param[in] x Input value for allGather
* @return Output array for allGather
*/
template<class type>
std::vector<type> allGather( const type &x ) const;
template <class type> std::vector<type> allGather(const type &x) const;
/*!
* Each processor sends every other processor an array
@ -823,7 +756,6 @@ public: // Member functions
template <class type>
std::vector<type> allGather(const std::vector<type> &x) const;
/*!
* Each processor sends every other processor a single value.
* The x_out array should be preallocated to a length equal
@ -832,9 +764,7 @@ public: // Member functions
* @param x_out Output array for allGather (must be preallocated to the size of the
* communicator)
*/
template<class type>
void allGather( const type &x_in, type *x_out ) const;
template <class type> void allGather(const type &x_in, type *x_out) const;
/*!
* Each processor sends an array of data to all other processors.
@ -863,16 +793,14 @@ public: // Member functions
*/
template <class type>
int allGather(const type *send_data, const int send_cnt, type *recv_data,
int *recv_cnt = nullptr, int *recv_disp = nullptr, bool known_recv = false ) const;
int *recv_cnt = nullptr, int *recv_disp = nullptr,
bool known_recv = false) const;
/*!
* This function combines sets from different processors to create a single master set
* @param set Input/Output std::set for the gather.
*/
template<class type>
void setGather( std::set<type> &set ) const;
template <class type> void setGather(std::set<type> &set) const;
/*!
* This function combines std::maps from different processors to create a single master std::map
@ -882,7 +810,6 @@ public: // Member functions
template <class KEY, class DATA>
void mapGather(std::map<KEY, DATA> &map) const;
/*!
* Each processor sends an array of n values to each processor.
* Each processor sends an array of n values to each processor.
@ -897,7 +824,6 @@ public: // Member functions
template <class type>
void allToAll(const int n, const type *send_data, type *recv_data) const;
/*!
* Each processor sends an array of data to the different processors.
* Each processor may send any size array to any processor. In the variable
@ -927,11 +853,11 @@ public: // Member functions
* and the sizes and displacements will be returned (if desired).
*/
template <class type>
int allToAll( const type *send_data, const int send_cnt[], const int send_disp[],
type *recv_data, int *recv_cnt = nullptr, int *recv_disp = nullptr,
int allToAll(const type *send_data, const int send_cnt[],
const int send_disp[], type *recv_data,
int *recv_cnt = nullptr, int *recv_disp = nullptr,
bool known_recv = false) const;
/*!
* \brief Send a list of proccesor ids to communicate
* \details This function communicates a list of proccesors to communicate.
@ -944,7 +870,6 @@ public: // Member functions
*/
std::vector<int> commRanks(const std::vector<int> &ranks) const;
/*!
* \brief Wait for a communication to finish
* \details Wait for a communication to finish.
@ -953,7 +878,6 @@ public: // Member functions
*/
static void wait(MPI_Request request);
/*!
* \brief Wait for any communication to finish.
* \details This function waits for any of the given communication requests to finish.
@ -964,7 +888,6 @@ public: // Member functions
*/
static int waitAny(int count, MPI_Request *request);
/*!
* \brief Wait for all communications to finish.
* \details This function waits for all of the given communication requests to finish.
@ -974,7 +897,6 @@ public: // Member functions
*/
static void waitAll(int count, MPI_Request *request);
/*!
* \brief Wait for some communications to finish.
* \details This function waits for one (or more) communications to finish.
@ -985,7 +907,6 @@ public: // Member functions
*/
static std::vector<int> waitSome(int count, MPI_Request *request);
/*!
* \brief Nonblocking test for a message
* \details This function performs a non-blocking test for a message.
@ -997,7 +918,6 @@ public: // Member functions
*/
int Iprobe(int source = -1, int tag = -1) const;
/*!
* \brief Blocking test for a message
* \details This function performs a blocking test for a message.
@ -1008,7 +928,6 @@ public: // Member functions
*/
int probe(int source = -1, int tag = -1) const;
/*!
* \brief Start a serial region
* \details This function will serialize MPI processes so that they run
@ -1018,14 +937,12 @@ public: // Member functions
*/
void serializeStart();
/*!
* \brief Stop a serial region
* \details Stop a serial region. See serializeStart for more information.
*/
void serializeStop();
/*!
* \brief Elapsed time
* \details This function returns the elapsed time on the calling processor
@ -1036,14 +953,12 @@ public: // Member functions
*/
static double time();
/*!
* \brief Timer resolution
* \details This function returns the timer resolution used by "time"
*/
static double tick();
/*!
* \brief Change the level of the internal timers
* \details This function changes the level of the timers used to profile MPI
@ -1051,7 +966,6 @@ public: // Member functions
*/
static void changeProfileLevel(int level) { profile_level = level; }
//! Return the total number of MPI_Comm objects that have been created
static size_t MPI_Comm_created() { return N_MPI_Comm_created; }
@ -1073,7 +987,6 @@ public: // Member functions
//! Stop MPI
static void stop_MPI();
/*!
* \brief Load balance
* \details This function will return a new communicator in which the ranks match
@ -1082,27 +995,28 @@ public: // Member functions
MPI loadBalance(double localPerformance, std::vector<double> work);
private: // Private helper functions for templated MPI operations;
template<class type>
void call_sumReduce( type *x, const int n = 1 ) const;
template <class type> void call_sumReduce(type *x, const int n = 1) const;
template <class type>
void call_sumReduce(const type *x, type *y, const int n = 1) const;
template <class type>
void call_minReduce( type *x, const int n = 1, int *rank_of_min = nullptr ) const;
void call_minReduce(type *x, const int n = 1,
int *rank_of_min = nullptr) const;
template <class type>
void call_minReduce(
const type *x, type *y, const int n = 1, int *rank_of_min = nullptr ) const;
void call_minReduce(const type *x, type *y, const int n = 1,
int *rank_of_min = nullptr) const;
template <class type>
void call_maxReduce( type *x, const int n = 1, int *rank_of_max = nullptr ) const;
void call_maxReduce(type *x, const int n = 1,
int *rank_of_max = nullptr) const;
template <class type>
void call_maxReduce(
const type *x, type *y, const int n = 1, int *rank_of_max = nullptr ) const;
void call_maxReduce(const type *x, type *y, const int n = 1,
int *rank_of_max = nullptr) const;
template <class type>
void call_bcast(type *x, const int n, const int root) const;
template <class type>
void call_allGather(const type &x_in, type *x_out) const;
template <class type>
void call_allGather(
const type *x_in, int size_in, type *x_out, int *size_out, int *disp_out ) const;
void call_allGather(const type *x_in, int size_in, type *x_out,
int *size_out, int *disp_out) const;
template <class type>
void call_sumScan(const type *x, type *y, int n = 1) const;
template <class type>
@ -1110,9 +1024,9 @@ private: // Private helper functions for templated MPI operations;
template <class type>
void call_maxScan(const type *x, type *y, int n = 1) const;
template <class type>
void call_allToAll( const type *send_data, const int send_cnt[], const int send_disp[],
type *recv_data, const int *recv_cnt, const int *recv_disp ) const;
void call_allToAll(const type *send_data, const int send_cnt[],
const int send_disp[], type *recv_data,
const int *recv_cnt, const int *recv_disp) const;
private: // data members
// The internal MPI communicator
@ -1157,14 +1071,11 @@ private: // data members
static volatile unsigned int N_MPI_Comm_destroyed;
};
} // namespace Utilities
// Include the default instantiations
// \cond HIDDEN_SYMBOLS
#include "common/MPI.I"
// \endcond
#endif

View File

@ -5,10 +5,8 @@
#include <cstring>
// Read a file into memory
std::vector<char> readFile( const std::string& filename )
{
std::vector<char> readFile(const std::string &filename) {
auto fid = fopen(filename.c_str(), "rb");
INSIST(fid, "File does not exist: " + filename);
fseek(fid, 0, SEEK_END);
@ -21,10 +19,8 @@ std::vector<char> readFile( const std::string& filename )
return data;
}
// Decompress a gzip buffer
std::vector<char> gunzip( const std::vector<char>& in )
{
std::vector<char> gunzip(const std::vector<char> &in) {
z_stream stream;
std::vector<char> out(1000000);
stream.next_in = (Bytef *)in.data();
@ -50,10 +46,8 @@ std::vector<char> gunzip( const std::vector<char>& in )
return out;
}
// Read the compressed micro CT data
Array<uint8_t> readMicroCT( const std::string& filename )
{
Array<uint8_t> readMicroCT(const std::string &filename) {
auto in = readFile(filename);
auto out = gunzip(in);
ASSERT(out.size() == 1024 * 1024 * 1024);
@ -62,10 +56,8 @@ Array<uint8_t> readMicroCT( const std::string& filename )
return data;
}
// Read the compressed micro CT data and distribute
Array<uint8_t> readMicroCT( const Database& domain, const Utilities::MPI& comm )
{
Array<uint8_t> readMicroCT(const Database &domain, const Utilities::MPI &comm) {
// Get the local problem info
auto n = domain.getVector<int>("n");
int rank = comm.getRank();
@ -84,11 +76,15 @@ Array<uint8_t> readMicroCT( const Database& domain, const Utilities::MPI& comm )
auto filename = domain.getScalar<std::string>("Filename");
char tmp[100];
if (filename.find("0x_0y_0z.gbd.gz") != std::string::npos) {
sprintf( tmp, "%ix_%iy_%iz.gbd.gz", srcRankInfo.ix, srcRankInfo.jy, srcRankInfo.kz );
filename = filename.replace( filename.find( "0x_0y_0z.gbd.gz" ), 15, std::string( tmp ) );
sprintf(tmp, "%ix_%iy_%iz.gbd.gz", srcRankInfo.ix, srcRankInfo.jy,
srcRankInfo.kz);
filename = filename.replace(filename.find("0x_0y_0z.gbd.gz"), 15,
std::string(tmp));
} else if (filename.find("x0_y0_z0.gbd.gz") != std::string::npos) {
sprintf( tmp, "x%i_y%i_z%i.gbd.gz", srcRankInfo.ix, srcRankInfo.jy, srcRankInfo.kz );
filename = filename.replace( filename.find( "x0_y0_z0.gbd.gz" ), 15, std::string( tmp ) );
sprintf(tmp, "x%i_y%i_z%i.gbd.gz", srcRankInfo.ix, srcRankInfo.jy,
srcRankInfo.kz);
filename = filename.replace(filename.find("x0_y0_z0.gbd.gz"), 15,
std::string(tmp));
} else {
ERROR("Invalid name for first file");
}

View File

@ -1,16 +1,13 @@
#ifndef READMICROCT_H
#define READMICROCT_H
#include "common/Array.h"
#include "common/Communication.h"
#include "common/Database.h"
#include "common/MPI.h"
Array<uint8_t> readMicroCT(const std::string &filename);
Array<uint8_t> readMicroCT(const Database &domain, const Utilities::MPI &comm);
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/ScaLBL.h"
#include <chrono>
@ -1356,6 +1372,14 @@ void ScaLBL_Communicator::SolidNeumannD3Q7(double *fq, double *BoundaryValue){
ScaLBL_Solid_Neumann_D3Q7(fq,BoundaryValue,bb_dist,bb_interactions,n_bb_d3q7);
}
void ScaLBL_Communicator::SolidDirichletAndNeumannD3Q7(double *fq, double *BoundaryValue, int *BoundaryLabel){
// fq is a D3Q7 distribution
// BoundaryValues is a list of values to assign at bounce-back solid sites
// BoundaryLabel: is a list of integer labels indicating the type of BCs
// 1-> Dirichlet BC; 2-> Neumann BC.
ScaLBL_Solid_DirichletAndNeumann_D3Q7(fq,BoundaryValue,BoundaryLabel,bb_dist,bb_interactions,n_bb_d3q7);
}
void ScaLBL_Communicator::SolidSlippingVelocityBCD3Q19(double *fq, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epsilon_LB, double tau, double rho0, double den_scale,double h, double time_conv){
// fq is a D3Q19 distribution

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ScaLBL.h */
/* \details Header file for Scalable Lattice Boltzmann Library
* Separate implementations for GPU and CPU must both follow the conventions defined in this header
@ -593,6 +609,8 @@ extern "C" void ScaLBL_Solid_Dirichlet_D3Q7(double *dist,double *BoundaryValue,i
extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist,double *BoundaryValue,int *BounceBackDist_list,int *BounceBackSolid_list,int N);
extern "C" void ScaLBL_Solid_DirichletAndNeumann_D3Q7(double *dist,double *BoundaryValue,int *BoundaryLabel,int *BounceBackDist_list,int *BounceBackSolid_list,int N);
extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epsilon_LB, double tau, double rho0,double den_scale, double h, double time_conv,
int *BounceBackDist_list, int *BounceBackSolid_list, int *FluidBoundary_list,
@ -700,6 +718,7 @@ public:
void SetupBounceBackList(IntArray &Map, signed char *id, int Np, bool SlippingVelBC=false);
void SolidDirichletD3Q7(double *fq, double *BoundaryValue);
void SolidNeumannD3Q7(double *fq, double *BoundaryValue);
void SolidDirichletAndNeumannD3Q7(double *fq, double *BoundaryValue, int *BoundaryLabel);
void SolidSlippingVelocityBCD3Q19(double *fq, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epslion_LB, double tau, double rho0, double den_scale,double h, double time_conv);
@ -786,6 +805,4 @@ private:
//......................................................................................
};
#endif

View File

@ -1,3 +1,35 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
@ -15,14 +47,15 @@
#include "common/SpherePack.h"
// Inline function to read line without a return argument
static inline void fgetl( char * str, int num, FILE * stream )
{
static inline void fgetl(char *str, int num, FILE *stream) {
char *ptr = fgets(str, num, stream);
if ( 0 ) {char *temp = (char *)&ptr; temp++;}
if (0) {
char *temp = (char *)&ptr;
temp++;
}
}
void WriteLocalSolidID(char *FILENAME, char *ID, int N)
{
void WriteLocalSolidID(char *FILENAME, char *ID, int N) {
char value;
ofstream File(FILENAME, ios::binary);
for (int n = 0; n < N; n++) {
@ -32,8 +65,7 @@ void WriteLocalSolidID(char *FILENAME, char *ID, int N)
File.close();
}
void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N)
{
void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N) {
double value;
ofstream File(FILENAME, ios::binary);
for (int n = 0; n < N; n++) {
@ -43,8 +75,8 @@ void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N)
File.close();
}
void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad)
{
void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy,
double *List_cz, double *List_rad) {
// Read in the full sphere pack
//...... READ IN THE SPHERES...................................
cout << "Reading the packing file..." << endl;
@ -69,14 +101,16 @@ void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *L
count++;
}
cout << "Number of spheres extracted is: " << count << endl;
INSIST( count==nspheres, "Specified number of spheres is probably incorrect!" );
INSIST(count == nspheres,
"Specified number of spheres is probably incorrect!");
// .............................................................
}
void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad,
void AssignLocalSolidID(char *ID, int nspheres, double *List_cx,
double *List_cy, double *List_cz, double *List_rad,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz)
{
int iproc, int jproc, int kproc, int nprocx, int nprocy,
int nprocz) {
// Use sphere lists to determine which nodes are in porespace
// Write out binary file for nodes
char value;
@ -131,18 +165,30 @@ void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy
kmin = int((cz - r) / hz) - 1;
kmax = int((cz + r) / hz) + 1;
// Obviously we have to do something at the edges
if (imin<0) imin = 0;
if (imin>Nx) imin = Nx;
if (imax<0) imax = 0;
if (imax>Nx) imax = Nx;
if (jmin<0) jmin = 0;
if (jmin>Ny) jmin = Ny;
if (jmax<0) jmax = 0;
if (jmax>Ny) jmax = Ny;
if (kmin<0) kmin = 0;
if (kmin>Nz) kmin = Nz;
if (kmax<0) kmax = 0;
if (kmax>Nz) kmax = Nz;
if (imin < 0)
imin = 0;
if (imin > Nx)
imin = Nx;
if (imax < 0)
imax = 0;
if (imax > Nx)
imax = Nx;
if (jmin < 0)
jmin = 0;
if (jmin > Ny)
jmin = Ny;
if (jmax < 0)
jmax = 0;
if (jmax > Ny)
jmax = Ny;
if (kmin < 0)
kmin = 0;
if (kmin > Nz)
kmin = Nz;
if (kmax < 0)
kmax = 0;
if (kmax > Nz)
kmax = Nz;
// Loop over the domain for this sphere (may be null)
for (i = imin; i < imax; i++) {
for (j = jmin; j < jmax; j++) {
@ -153,7 +199,9 @@ void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy
z = k * hz;
value = 1;
// if inside sphere, set to zero
if ( (cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z) < r*r){
if ((cx - x) * (cx - x) + (cy - y) * (cy - y) +
(cz - z) * (cz - z) <
r * r) {
value = 0;
}
// get the position in the list
@ -167,10 +215,11 @@ void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy
}
}
void SignedDistance(double *Distance, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad,
void SignedDistance(double *Distance, int nspheres, double *List_cx,
double *List_cy, double *List_cz, double *List_rad,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz)
{
int iproc, int jproc, int kproc, int nprocx, int nprocy,
int nprocz) {
// Use sphere lists to determine which nodes are in porespace
// Write out binary file for nodes
int N = Nx * Ny * Nz; // Domain size, including the halo
@ -221,18 +270,30 @@ void SignedDistance(double *Distance, int nspheres, double *List_cx, double *Lis
kmin = int((cz - 2 * r) / hz);
kmax = int((cz + 2 * r) / hz) + 2;
// Obviously we have to do something at the edges
if (imin<0) imin = 0;
if (imin>Nx) imin = Nx;
if (imax<0) imax = 0;
if (imax>Nx) imax = Nx;
if (jmin<0) jmin = 0;
if (jmin>Ny) jmin = Ny;
if (jmax<0) jmax = 0;
if (jmax>Ny) jmax = Ny;
if (kmin<0) kmin = 0;
if (kmin>Nz) kmin = Nz;
if (kmax<0) kmax = 0;
if (kmax>Nz) kmax = Nz;
if (imin < 0)
imin = 0;
if (imin > Nx)
imin = Nx;
if (imax < 0)
imax = 0;
if (imax > Nx)
imax = Nx;
if (jmin < 0)
jmin = 0;
if (jmin > Ny)
jmin = Ny;
if (jmax < 0)
jmax = 0;
if (jmax > Ny)
jmax = Ny;
if (kmin < 0)
kmin = 0;
if (kmin > Nz)
kmin = Nz;
if (kmax < 0)
kmax = 0;
if (kmax > Nz)
kmax = Nz;
// Loop over the domain for this sphere (may be null)
for (i = imin; i < imax; i++) {
for (j = jmin; j < jmax; j++) {
@ -245,15 +306,18 @@ void SignedDistance(double *Distance, int nspheres, double *List_cx, double *Lis
// get the position in the list
n = k * Nx * Ny + j * Nx + i;
// Compute the distance
distance = sqrt((cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z)) - r;
distance = sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y) +
(cz - z) * (cz - z)) -
r;
// Assign the minimum distance
if (distance < Distance[n]) Distance[n] = distance;
if (distance < Distance[n])
Distance[n] = distance;
}
}
}
}
// Map the distance to lattice units
for (n=0; n<N; n++) Distance[n] = Distance[n]/hx;
for (n = 0; n < N; n++)
Distance[n] = Distance[n] / hx;
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SpherePack_INC
#define SpherePack_INC
@ -24,14 +40,19 @@ void WriteLocalSolidID(char *FILENAME, char *ID, int N);
void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N);
void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad);
void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy,
double *List_cz, double *List_rad);
void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad,
void AssignLocalSolidID(char *ID, int nspheres, double *List_cx,
double *List_cy, double *List_cz, double *List_rad,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz);
int iproc, int jproc, int kproc, int nprocx, int nprocy,
int nprocz);
void SignedDistance(double *Distance, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad,
void SignedDistance(double *Distance, int nspheres, double *List_cx,
double *List_cy, double *List_cz, double *List_rad,
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz);
int iproc, int jproc, int kproc, int nprocx, int nprocy,
int nprocz);
#endif

108
common/UnitTest.cpp Executable file → Normal file
View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/UnitTest.h"
#include "common/Utilities.h"
#include <cstring>
@ -6,23 +22,19 @@
#include <string>
#include <vector>
#define pout std::cout
#define printp printf
/********************************************************************
* Constructor/Destructor *
********************************************************************/
UnitTest::UnitTest()
{
UnitTest::UnitTest() {
#ifdef USE_MPI
comm = MPI_COMM_WORLD;
#endif
}
UnitTest::~UnitTest() { reset(); }
void UnitTest::reset()
{
void UnitTest::reset() {
mutex.lock();
// Clear the data forcing a reallocation
std::vector<std::string>().swap(pass_messages);
@ -31,36 +43,30 @@ void UnitTest::reset()
mutex.unlock();
}
/********************************************************************
* Add a pass, fail, expected failure message in a thread-safe way *
********************************************************************/
void UnitTest::passes( const std::string &in )
{
void UnitTest::passes(const std::string &in) {
mutex.lock();
pass_messages.push_back(in);
mutex.unlock();
}
void UnitTest::failure( const std::string &in )
{
void UnitTest::failure(const std::string &in) {
mutex.lock();
fail_messages.push_back(in);
mutex.unlock();
}
void UnitTest::expected_failure( const std::string &in )
{
void UnitTest::expected_failure(const std::string &in) {
mutex.lock();
expected_fail_messages.push_back(in);
mutex.unlock();
}
/********************************************************************
* Print a global report *
* Note: only rank 0 will print, all messages will be aggregated *
********************************************************************/
inline std::vector<int> UnitTest::allGather( int value ) const
{
inline std::vector<int> UnitTest::allGather(int value) const {
int size = getSize();
std::vector<int> data(size, value);
#ifdef USE_MPI
@ -69,15 +75,14 @@ inline std::vector<int> UnitTest::allGather( int value ) const
#endif
return data;
}
inline void UnitTest::barrier() const
{
inline void UnitTest::barrier() const {
#ifdef USE_MPI
if (getSize() > 1)
MPI_Barrier(comm);
#endif
}
static inline void print_messages( const std::vector<std::vector<std::string>> &messages )
{
static inline void
print_messages(const std::vector<std::vector<std::string>> &messages) {
if (messages.size() > 1) {
for (size_t i = 0; i < messages.size(); i++) {
if (!messages[i].empty()) {
@ -91,8 +96,7 @@ static inline void print_messages( const std::vector<std::vector<std::string>> &
pout << " " << j << std::endl;
}
}
void UnitTest::report( const int level0 ) const
{
void UnitTest::report(const int level0) const {
mutex.lock();
int size = getSize();
int rank = getRank();
@ -128,7 +132,8 @@ void UnitTest::report( const int level0 ) const
fail_messages_rank = UnitTest::gatherMessages(fail_messages, 2);
// Get the expected_fail messages
if ((level == 1 && N_expected_fail_tot <= 50) || level == 2)
expected_fail_rank = UnitTest::gatherMessages( expected_fail_messages, 2 );
expected_fail_rank =
UnitTest::gatherMessages(expected_fail_messages, 2);
// Print the results of all messages (only rank 0 will print)
if (rank == 0) {
pout << std::endl;
@ -138,11 +143,14 @@ void UnitTest::report( const int level0 ) const
// We want to print a summary
if (size > 8) {
// Print 1 summary for all processors
printp( " %i tests passed (use report level 2 for more detail)\n", N_pass_tot );
printp(" %i tests passed (use report level 2 for more "
"detail)\n",
N_pass_tot);
} else {
// Print a summary for each processor
for (int i = 0; i < size; i++)
printp( " %i tests passed (proc %i) (use report level 2 for more detail)\n",
printp(" %i tests passed (proc %i) (use report level 2 "
"for more detail)\n",
N_pass[i], i);
}
} else {
@ -158,11 +166,14 @@ void UnitTest::report( const int level0 ) const
// We want to print a summary
if (size > 8) {
// Print 1 summary for all processors
printp( " %i tests failed (use report level 2 for more detail)\n", N_fail_tot );
printp(" %i tests failed (use report level 2 for more "
"detail)\n",
N_fail_tot);
} else {
// Print a summary for each processor
for (int i = 0; i < size; i++)
printp( " %i tests failed (proc %i) (use report level 2 for more detail)\n",
printp(" %i tests failed (proc %i) (use report level 2 "
"for more detail)\n",
N_fail[i], i);
}
} else {
@ -178,12 +189,14 @@ void UnitTest::report( const int level0 ) const
// We want to print a summary
if (size > 8) {
// Print 1 summary for all processors
printp( " %i tests expected failed (use report level 2 for more detail)\n",
printp(" %i tests expected failed (use report level 2 for "
"more detail)\n",
N_expected_fail_tot);
} else {
// Print a summary for each processor
for (int i = 0; i < size; i++)
printp( " %i tests expected failed (proc %i) (use report level 2 for more "
printp(" %i tests expected failed (proc %i) (use "
"report level 2 for more "
"detail)\n",
N_expected_fail[i], i);
}
@ -197,17 +210,17 @@ void UnitTest::report( const int level0 ) const
}
// Add a barrier to synchronize all processors (rank 0 is much slower)
barrier();
Utilities::sleep_ms( 10 ); // Need a brief pause to allow any printing to finish
Utilities::sleep_ms(
10); // Need a brief pause to allow any printing to finish
mutex.unlock();
}
/********************************************************************
* Gather the messages to rank 0 *
********************************************************************/
std::vector<std::vector<std::string>> UnitTest::gatherMessages(
const std::vector<std::string> &local_messages, int tag ) const
{
std::vector<std::vector<std::string>>
UnitTest::gatherMessages(const std::vector<std::string> &local_messages,
int tag) const {
const int rank = getRank();
const int size = getSize();
std::vector<std::vector<std::string>> messages(size);
@ -226,13 +239,11 @@ std::vector<std::vector<std::string>> UnitTest::gatherMessages(
return messages;
}
/********************************************************************
* Pack and send the given messages *
********************************************************************/
void UnitTest::pack_message_stream(
const std::vector<std::string> &messages, const int rank, const int tag ) const
{
void UnitTest::pack_message_stream(const std::vector<std::string> &messages,
const int rank, const int tag) const {
#ifdef USE_MPI
// Get the size of the messages
auto N_messages = (int)messages.size();
@ -268,12 +279,11 @@ void UnitTest::pack_message_stream(
#endif
}
/********************************************************************
* Receive and unpack a message stream *
********************************************************************/
std::vector<std::string> UnitTest::unpack_message_stream( const int rank, const int tag ) const
{
std::vector<std::string> UnitTest::unpack_message_stream(const int rank,
const int tag) const {
#ifdef USE_MPI
// Probe the message to get the message size
MPI_Status status;
@ -312,12 +322,10 @@ std::vector<std::string> UnitTest::unpack_message_stream( const int rank, const
#endif
}
/********************************************************************
* Other functions *
********************************************************************/
int UnitTest::getRank() const
{
int UnitTest::getRank() const {
int rank = 0;
#ifdef USE_MPI
int flag = 0;
@ -327,8 +335,7 @@ int UnitTest::getRank() const
#endif
return rank;
}
int UnitTest::getSize() const
{
int UnitTest::getSize() const {
int size = 1;
#ifdef USE_MPI
int flag = 0;
@ -338,8 +345,7 @@ int UnitTest::getSize() const
#endif
return size;
}
size_t UnitTest::NumPassGlobal() const
{
size_t UnitTest::NumPassGlobal() const {
size_t num = pass_messages.size();
#ifdef USE_MPI
if (getSize() > 1) {
@ -351,8 +357,7 @@ size_t UnitTest::NumPassGlobal() const
#endif
return num;
}
size_t UnitTest::NumFailGlobal() const
{
size_t UnitTest::NumFailGlobal() const {
size_t num = fail_messages.size();
#ifdef USE_MPI
if (getSize() > 1) {
@ -364,8 +369,7 @@ size_t UnitTest::NumFailGlobal() const
#endif
return num;
}
size_t UnitTest::NumExpectedFailGlobal() const
{
size_t UnitTest::NumExpectedFailGlobal() const {
size_t num = expected_fail_messages.size();
#ifdef USE_MPI
if (getSize() > 1) {

37
common/UnitTest.h Executable file → Normal file
View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_UnitTest
#define included_UnitTest
@ -9,7 +25,6 @@
#include "mpi.h"
#endif
/*!
* @brief Class UnitTest is simple utility for running unit tests.
* It provides basic routines for tracing success or failure of tests,
@ -28,8 +43,7 @@
* \endcode
*/
class UnitTest
{
class UnitTest {
public:
//! Constructor
UnitTest();
@ -53,7 +67,9 @@ public:
virtual size_t NumFailLocal() const { return fail_messages.size(); }
//! Return the number of expected failed tests locally
virtual size_t NumExpectedFailLocal() const { return expected_fail_messages.size(); }
virtual size_t NumExpectedFailLocal() const {
return expected_fail_messages.size();
}
//! Return the number of passed tests locally
virtual size_t NumPassGlobal() const;
@ -102,19 +118,20 @@ private:
// Function to pack the messages into a single data stream and send to the given processor
// Note: This function does not return until the message stream has been sent
void pack_message_stream(
const std::vector<std::string> &messages, const int rank, const int tag ) const;
void pack_message_stream(const std::vector<std::string> &messages,
const int rank, const int tag) const;
// Function to unpack the messages from a single data stream
// Note: This function does not return until the message stream has been received
std::vector<std::string> unpack_message_stream( const int rank, const int tag ) const;
std::vector<std::string> unpack_message_stream(const int rank,
const int tag) const;
// Helper functions
inline void barrier() const;
inline std::vector<int> allGather(int value) const;
inline std::vector<std::vector<std::string>> gatherMessages(
const std::vector<std::string> &local_messages, int tag ) const;
inline std::vector<std::vector<std::string>>
gatherMessages(const std::vector<std::string> &local_messages,
int tag) const;
};
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/Units.h"
#include "common/Utilities.h"
@ -5,19 +21,16 @@
#include <cmath>
#include <string>
constexpr double Units::d_pow10[22];
constexpr char Units::d_prefixSymbol[];
/********************************************************************
* Constructors *
********************************************************************/
Units::Units() : d_prefix(UnitPrefix::unknown), d_unit(UnitValue::unknown) {}
Units::Units(UnitPrefix p, UnitValue u) : d_prefix(p), d_unit(u) {}
Units::Units(const std::string &unit)
: d_prefix( UnitPrefix::unknown ), d_unit( UnitValue::unknown )
{
: d_prefix(UnitPrefix::unknown), d_unit(UnitValue::unknown) {
// Parse the string to get it into a more friendly format
auto tmp = unit;
tmp.erase(std::remove(tmp.begin(), tmp.end(), ' '), tmp.end());
@ -36,7 +49,8 @@ Units::Units( const std::string& unit )
} else {
d_prefix = getUnitPrefix(tmp.substr(0, 1));
d_unit = getUnitValue(tmp.substr(1));
if ( d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown ) {
if (d_prefix == UnitPrefix::unknown ||
d_unit == UnitValue::unknown) {
d_prefix = UnitPrefix::none;
d_unit = getUnitValue(tmp);
}
@ -44,12 +58,10 @@ Units::Units( const std::string& unit )
}
}
/********************************************************************
* Get prefix *
********************************************************************/
Units::UnitPrefix Units::getUnitPrefix( const std::string& str ) noexcept
{
Units::UnitPrefix Units::getUnitPrefix(const std::string &str) noexcept {
Units::UnitPrefix value = UnitPrefix::unknown;
if (str.empty()) {
value = UnitPrefix::none;
@ -97,12 +109,10 @@ Units::UnitPrefix Units::getUnitPrefix( const std::string& str ) noexcept
return value;
}
/********************************************************************
* Get unit value *
********************************************************************/
Units::UnitValue Units::getUnitValue( const std::string& str ) noexcept
{
Units::UnitValue Units::getUnitValue(const std::string &str) noexcept {
Units::UnitValue value = UnitValue::unknown;
if (str == "meter" || str == "m") {
value = UnitValue::meter;
@ -126,12 +136,10 @@ Units::UnitValue Units::getUnitValue( const std::string& str ) noexcept
return value;
}
/********************************************************************
* Get unit type *
********************************************************************/
Units::UnitType Units::getUnitType( UnitValue u ) noexcept
{
Units::UnitType Units::getUnitType(UnitValue u) noexcept {
switch (u) {
case UnitValue::meter:
return UnitType::length;
@ -154,12 +162,10 @@ Units::UnitType Units::getUnitType( UnitValue u ) noexcept
}
}
/********************************************************************
* Convert to another unit system *
********************************************************************/
double Units::convert( const Units& rhs ) const noexcept
{
double Units::convert(const Units &rhs) const noexcept {
if (this->operator==(rhs))
return 1;
// Convert the prefix
@ -182,17 +188,14 @@ double Units::convert( const Units& rhs ) const noexcept
return cp * cu;
}
/********************************************************************
* Write a string for the units *
********************************************************************/
std::string Units::str() const
{
std::string Units::str() const {
ASSERT(!isNull());
return std::string(str(d_prefix).data()) + str(d_unit);
}
std::array<char, 3> Units::str( UnitPrefix p ) noexcept
{
std::array<char, 3> Units::str(UnitPrefix p) noexcept {
std::array<char, 3> str;
str[0] = d_prefixSymbol[static_cast<int8_t>(p)];
str[1] = 0;
@ -201,8 +204,7 @@ std::array<char, 3> Units::str( UnitPrefix p ) noexcept
str[1] = 'a';
return str;
}
std::string Units::str( UnitValue u )
{
std::string Units::str(UnitValue u) {
if (u == UnitValue::meter) {
return "m";
} else if (u == UnitValue::gram) {

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_Units
#define included_Units
@ -8,10 +24,8 @@
#include <string>
#include <vector>
//! Unit system class
class Units final
{
class Units final {
public:
//! Enum to hold prefix
enum class UnitPrefix : int8_t {
@ -65,7 +79,6 @@ public:
unknown
};
public:
//! Constructor
Units();
@ -98,8 +111,7 @@ public:
double convert(const Units &) const noexcept;
//! Convert a prefix to a scalar
static inline double convert( UnitPrefix x ) noexcept
{
static inline double convert(UnitPrefix x) noexcept {
return d_pow10[static_cast<int8_t>(x)];
}
@ -113,27 +125,28 @@ public:
static std::string str(UnitValue);
//! Operator ==
inline bool operator==( const Units& rhs ) const noexcept
{
inline bool operator==(const Units &rhs) const noexcept {
return d_prefix == rhs.d_prefix && d_unit == rhs.d_unit;
}
//! Operator !=
inline bool operator!=( const Units& rhs ) const noexcept
{
inline bool operator!=(const Units &rhs) const noexcept {
return d_prefix != rhs.d_prefix || d_unit != rhs.d_unit;
}
//! Check if unit is null
bool isNull() const { return d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown; }
bool isNull() const {
return d_prefix == UnitPrefix::unknown || d_unit == UnitValue::unknown;
}
protected:
UnitPrefix d_prefix;
UnitValue d_unit;
private:
constexpr static double d_pow10[22] = { 1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-9, 1e-6, 1e-3,
1e-2, 0.1, 1, 10, 100, 1000, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 0 };
constexpr static double d_pow10[22] = {
1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-9, 1e-6, 1e-3, 1e-2, 0.1, 1,
10, 100, 1000, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 0};
constexpr static char d_prefixSymbol[] = "yzafpnumcd\0dhkMGTPEZYu";
};

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/Utilities.h"
#include "StackTrace/StackTrace.h"
#include "StackTrace/ErrorHandlers.h"
@ -15,7 +31,6 @@
#include <math.h>
#include <mutex>
// OS specific includes / definitions
// clang-format off
#if defined( WIN32 ) || defined( _WIN32 ) || defined( WIN64 ) || defined( _WIN64 )
@ -29,16 +44,13 @@
#endif
// clang-format on
// Mutex for Utility functions
static std::mutex Utilities_mutex;
/****************************************************************************
* Function to perform the default startup/shutdown sequences *
****************************************************************************/
void Utilities::startup( int argc, char **argv, bool multiple )
{
void Utilities::startup(int argc, char **argv, bool multiple) {
NULL_USE(argc);
NULL_USE(argv);
// Disable OpenMP
@ -53,7 +65,9 @@ void Utilities::startup( int argc, char **argv, bool multiple )
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
std::cerr << "Warning: Failed to start MPI with necessary thread support, thread support will be disabled" << std::endl;
std::cerr << "Warning: Failed to start MPI with necessary "
"thread support, thread support will be disabled"
<< std::endl;
}
StackTrace::globalCallStackInitialize(MPI_COMM_WORLD);
} else {
@ -64,8 +78,7 @@ void Utilities::startup( int argc, char **argv, bool multiple )
Utilities::setAbortBehavior(true, 3);
Utilities::setErrorHandlers();
}
void Utilities::shutdown()
{
void Utilities::shutdown() {
// Clear the error handlers
Utilities::clearErrorHandlers();
StackTrace::clearSignals();
@ -85,12 +98,10 @@ void Utilities::shutdown()
#endif
}
/****************************************************************************
* Function to set an environemental variable *
****************************************************************************/
void Utilities::setenv( const std::string &name, const std::string &value )
{
void Utilities::setenv(const std::string &name, const std::string &value) {
Utilities_mutex.lock();
#if defined(USE_LINUX) || defined(USE_MAC)
bool pass = false;
@ -107,15 +118,15 @@ void Utilities::setenv( const std::string &name, const std::string &value )
if (!pass) {
char msg[1024];
if (!value.empty())
sprintf(
msg, "Error setting enviornmental variable: %s=%s\n", name.data(), value.data() );
sprintf(msg, "Error setting enviornmental variable: %s=%s\n",
name.data(), value.data());
else
sprintf( msg, "Error clearing enviornmental variable: %s\n", name.data() );
sprintf(msg, "Error clearing enviornmental variable: %s\n",
name.data());
ERROR(msg);
}
}
std::string Utilities::getenv( const std::string &name )
{
std::string Utilities::getenv(const std::string &name) {
std::string var;
Utilities_mutex.lock();
auto tmp = std::getenv(name.data());
@ -125,12 +136,10 @@ std::string Utilities::getenv( const std::string &name )
return var;
}
/****************************************************************************
* Factor a number into it's prime factors *
****************************************************************************/
std::vector<int> Utilities::factor(size_t number)
{
std::vector<int> Utilities::factor(size_t number) {
if (number <= 3)
return std::vector<int>(1, (int)number);
size_t i, n, n_max;
@ -138,7 +147,8 @@ std::vector<int> Utilities::factor(size_t number)
// Compute the maximum number of factors
int N_primes_max = 1;
n = number;
while (n >>= 1) ++N_primes_max;
while (n >>= 1)
++N_primes_max;
// Initialize n, factors
n = number;
std::vector<int> factors;
@ -177,14 +187,7 @@ std::vector<int> Utilities::factor(size_t number)
return factors;
}
/****************************************************************************
* Dummy function to prevent compiler from optimizing away variable *
****************************************************************************/
void Utilities::nullUse( void* data )
{
NULL_USE(data);
}
void Utilities::nullUse(void *data) { NULL_USE(data); }

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef included_Utilities
#define included_Utilities
@ -6,10 +22,8 @@
#include "StackTrace/Utilities.h"
namespace Utilities {
// Functions inherited from StackTrace::Utilities
using StackTrace::Utilities::abort;
using StackTrace::Utilities::cause_segfault;
@ -19,11 +33,10 @@ using StackTrace::Utilities::getMemoryUsage;
using StackTrace::Utilities::getSystemMemory;
using StackTrace::Utilities::setAbortBehavior;
using StackTrace::Utilities::setErrorHandlers;
using StackTrace::Utilities::tick;
using StackTrace::Utilities::time;
using StackTrace::Utilities::sleep_ms;
using StackTrace::Utilities::sleep_s;
using StackTrace::Utilities::tick;
using StackTrace::Utilities::time;
/*!
* \brief Start MPI, error handlers
@ -40,7 +53,6 @@ void startup( int argc, char **argv, bool multiple=true );
*/
void shutdown();
/*!
* Get an environmental variable
* @param name The name of the environmental variable
@ -48,7 +60,6 @@ void shutdown();
*/
std::string getenv(const std::string &name);
/*!
* Set an environmental variable
* @param name The name of the environmental variable
@ -56,28 +67,21 @@ std::string getenv( const std::string &name );
*/
void setenv(const std::string &name, const std::string &value);
//! std::string version of sprintf
inline std::string stringf(const char *format, ...);
//! Factor a number into it's prime factors
std::vector<int> factor(size_t number);
//! Null use function
void nullUse(void *);
} // namespace Utilities
#include "common/UtilityMacros.h"
// stringf
inline std::string Utilities::stringf( const char *format, ... )
{
inline std::string Utilities::stringf(const char *format, ...) {
va_list ap;
va_start(ap, format);
char tmp[4096];
@ -86,5 +90,4 @@ inline std::string Utilities::stringf( const char *format, ... )
return std::string(tmp);
}
#endif

View File

@ -1,21 +1,16 @@
#ifndef included_Utilities_hpp
#define included_Utilities_hpp
#include "Utilities.h"
#include <vector>
namespace Utilities {
/************************************************************************
* templated quicksort routines *
************************************************************************/
template<class T>
void quicksort( std::vector<T> &x )
{
template <class T> void quicksort(std::vector<T> &x) {
if (x.size() <= 1u)
return;
T *arr = &x[0];
@ -45,11 +40,13 @@ void quicksort( std::vector<T> &x )
}
if (jstack == 0)
return;
ir = istack[jstack]; // Pop stack and begin a new round of partitioning.
ir = istack
[jstack]; // Pop stack and begin a new round of partitioning.
l = istack[jstack - 1];
jstack -= 2;
} else {
k = ( l + ir ) / 2; // Choose median of left, center and right elements as partitioning
k = (l + ir) /
2; // Choose median of left, center and right elements as partitioning
// element a. Also rearrange so that a(l) < a(l+1) < a(ir).
tmp_a = arr[k];
arr[k] = arr[l + 1];
@ -100,8 +97,7 @@ void quicksort( std::vector<T> &x )
}
}
template <class T1, class T2>
void quicksort( std::vector<T1> &x, std::vector<T2> &y )
{
void quicksort(std::vector<T1> &x, std::vector<T2> &y) {
if (x.size() <= 1u)
return;
T1 *arr = &x[0];
@ -137,11 +133,13 @@ void quicksort( std::vector<T1> &x, std::vector<T2> &y )
}
if (jstack == 0)
return;
ir = istack[jstack]; // Pop stack and begin a new round of partitioning.
ir = istack
[jstack]; // Pop stack and begin a new round of partitioning.
l = istack[jstack - 1];
jstack -= 2;
} else {
k = ( l + ir ) / 2; // Choose median of left, center and right elements as partitioning
k = (l + ir) /
2; // Choose median of left, center and right elements as partitioning
// element a. Also rearrange so that a(l) ? a(l+1) ? a(ir).
tmp_a = arr[k];
arr[k] = arr[l + 1];
@ -209,9 +207,7 @@ void quicksort( std::vector<T1> &x, std::vector<T2> &y )
}
}
}
template<class T>
void unique( std::vector<T> &x )
{
template <class T> void unique(std::vector<T> &x) {
if (x.size() <= 1)
return;
// First perform a quicksort
@ -228,7 +224,6 @@ void unique( std::vector<T> &x )
x.resize(pos);
}
}
} // namespace Utilities
#endif

View File

@ -1,3 +1,19 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// This file contains useful macros including ERROR, WARNING, INSIST, ASSERT, etc.
#ifndef included_UtilityMacros
#define included_UtilityMacros
@ -8,7 +24,6 @@
#include <sstream>
#include <stdexcept>
/*! \defgroup Macros Set of utility macro functions
* \details These functions are a list of C++ macros that are used
* for common operations, including checking for errors.
@ -16,7 +31,6 @@
* @{
*/
/*! \def NULL_STATEMENT
* \brief A null statement
* \details A statement that does nothing, for insure++ make it something
@ -34,7 +48,6 @@
#endif
#endif
/*! \def NULL_USE(variable)
* \brief A null use of a variable
* \details A null use of a variable, use to avoid GNU compiler warnings about unused variables.
@ -50,7 +63,6 @@
} while (0)
#endif
/*! \def ERROR(MSG)
* \brief Throw error
* \details Throw an error exception from within any C++ source code. The
@ -63,7 +75,6 @@
::Utilities::abort(MSG, __FILE__, __LINE__); \
} while (0)
/*! \def WARNING(MSG)
* \brief Print a warning
* \details Print a warning without exit. Print file and line number of the warning.
@ -77,7 +88,6 @@
tboxos.str().c_str(), __FILE__, __LINE__); \
} while (0)
/*! \def ASSERT(EXP)
* \brief Assert error
* \details Throw an error exception from within any C++ source code if the
@ -95,7 +105,6 @@
} \
} while (0)
/*! \def INSIST(EXP,MSG)
* \brief Insist error
* \details Throw an error exception from within any C++ source code if the
@ -105,7 +114,8 @@
* \param EXP Expression to evaluate
* \param MSG Debug message to print
*/
#define INSIST(EXP,MSG) do { \
#define INSIST(EXP, MSG) \
do { \
if (!(EXP)) { \
std::stringstream tboxos; \
tboxos << "Failed insist: " << #EXP << std::endl; \
@ -114,7 +124,6 @@
} \
} while (0)
/**
* Macro for use when assertions are to be included
* only when debugging.
@ -132,7 +141,6 @@
#define CHECK_ASSERT(EXP)
#endif
/*! \def DISABLE_WARNINGS
* \brief Reenable warnings
* \details This will re-enable warnings after a call to DIASABLE_WARNINGS
@ -173,9 +181,6 @@
#endif
// clang-format on
/*! @} */
#endif

View File

@ -3,8 +3,8 @@ This class implements support for halo widths larger than 1
*/
#include "common/WideHalo.h"
ScaLBLWideHalo_Communicator::ScaLBLWideHalo_Communicator(std::shared_ptr <Domain> Dm, int width)
{
ScaLBLWideHalo_Communicator::ScaLBLWideHalo_Communicator(
std::shared_ptr<Domain> Dm, int width) {
//......................................................................................
Lock = false; // unlock the communicator
//......................................................................................
@ -62,123 +62,283 @@ ScaLBLWideHalo_Communicator::ScaLBLWideHalo_Communicator(std::shared_ptr <Domain
/* Fill in communications patterns for the lists */
/* Send lists */
sendCount_x =getHaloBlock(width,2*width,width,Nyh-width,width,Nzh-width,dvcSendList_x);
sendCount_X =getHaloBlock(Nxh-2*width,Nxh-width,width,Nyh-width,width,Nzh-width,dvcSendList_X);
sendCount_y =getHaloBlock(width,Nxh-width,width,2*width,width,Nzh-width,dvcSendList_y);
sendCount_Y =getHaloBlock(width,Nxh-width,Nyh-2*width,Nyh-width,width,Nzh-width,dvcSendList_Y);
sendCount_z =getHaloBlock(width,Nxh-width,width,Nyh-width,width,2*width,dvcSendList_z);
sendCount_Z =getHaloBlock(width,Nxh-width,width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_Z);
sendCount_x = getHaloBlock(width, 2 * width, width, Nyh - width, width,
Nzh - width, dvcSendList_x);
sendCount_X = getHaloBlock(Nxh - 2 * width, Nxh - width, width, Nyh - width,
width, Nzh - width, dvcSendList_X);
sendCount_y = getHaloBlock(width, Nxh - width, width, 2 * width, width,
Nzh - width, dvcSendList_y);
sendCount_Y = getHaloBlock(width, Nxh - width, Nyh - 2 * width, Nyh - width,
width, Nzh - width, dvcSendList_Y);
sendCount_z = getHaloBlock(width, Nxh - width, width, Nyh - width, width,
2 * width, dvcSendList_z);
sendCount_Z = getHaloBlock(width, Nxh - width, width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_Z);
// xy
sendCount_xy =getHaloBlock(width,2*width,width,2*width,width,Nzh-width,dvcSendList_xy);
sendCount_xY =getHaloBlock(width,2*width,Nyh-2*width,Nyh-width,width,Nzh-width,dvcSendList_xY);
sendCount_Xy =getHaloBlock(Nxh-2*width,Nxh-width,width,2*width,width,Nzh-width,dvcSendList_Xy);
sendCount_XY =getHaloBlock(Nxh-2*width,Nxh-width,Nyh-2*width,Nyh-width,width,Nzh-width,dvcSendList_XY);
sendCount_xy = getHaloBlock(width, 2 * width, width, 2 * width, width,
Nzh - width, dvcSendList_xy);
sendCount_xY = getHaloBlock(width, 2 * width, Nyh - 2 * width, Nyh - width,
width, Nzh - width, dvcSendList_xY);
sendCount_Xy = getHaloBlock(Nxh - 2 * width, Nxh - width, width, 2 * width,
width, Nzh - width, dvcSendList_Xy);
sendCount_XY =
getHaloBlock(Nxh - 2 * width, Nxh - width, Nyh - 2 * width, Nyh - width,
width, Nzh - width, dvcSendList_XY);
// xz
sendCount_xz =getHaloBlock(width,2*width,width,Nyh-width,width,2*width,dvcSendList_xz);
sendCount_xZ =getHaloBlock(width,2*width,width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_xZ);
sendCount_Xz =getHaloBlock(Nxh-2*width,Nxh-width,width,Nyh-width,width,2*width,dvcSendList_Xz);
sendCount_XZ =getHaloBlock(Nxh-2*width,Nxh-width,width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_XZ);
sendCount_xz = getHaloBlock(width, 2 * width, width, Nyh - width, width,
2 * width, dvcSendList_xz);
sendCount_xZ = getHaloBlock(width, 2 * width, width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_xZ);
sendCount_Xz = getHaloBlock(Nxh - 2 * width, Nxh - width, width,
Nyh - width, width, 2 * width, dvcSendList_Xz);
sendCount_XZ =
getHaloBlock(Nxh - 2 * width, Nxh - width, width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_XZ);
// yz
sendCount_yz =getHaloBlock(width,Nxh-width,width,2*width,width,2*width,dvcSendList_yz);
sendCount_yZ =getHaloBlock(width,Nxh-width,width,2*width,Nzh-2*width,Nzh-width,dvcSendList_yZ);
sendCount_Yz =getHaloBlock(width,Nxh-width,Nyh-2*width,Nyh-width,width,2*width,dvcSendList_Yz);
sendCount_YZ =getHaloBlock(width,Nxh-width,Nyh-2*width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_YZ);
sendCount_yz = getHaloBlock(width, Nxh - width, width, 2 * width, width,
2 * width, dvcSendList_yz);
sendCount_yZ = getHaloBlock(width, Nxh - width, width, 2 * width,
Nzh - 2 * width, Nzh - width, dvcSendList_yZ);
sendCount_Yz = getHaloBlock(width, Nxh - width, Nyh - 2 * width,
Nyh - width, width, 2 * width, dvcSendList_Yz);
sendCount_YZ =
getHaloBlock(width, Nxh - width, Nyh - 2 * width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_YZ);
// xyz
sendCount_xyz =getHaloBlock(width,2*width,width,2*width,width,2*width,dvcSendList_xyz);
sendCount_xyZ =getHaloBlock(width,2*width,width,2*width,Nzh-2*width,Nzh-width,dvcSendList_xyZ);
sendCount_xYz =getHaloBlock(width,2*width,Nyh-2*width,Nyh-width,width,2*width,dvcSendList_xYz);
sendCount_xYZ =getHaloBlock(width,2*width,Nyh-2*width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_xYZ);
sendCount_Xyz =getHaloBlock(Nxh-2*width,Nxh-width,width,2*width,width,2*width,dvcSendList_Xyz);
sendCount_XyZ =getHaloBlock(Nxh-2*width,Nxh-width,width,2*width,Nzh-2*width,Nzh-width,dvcSendList_XyZ);
sendCount_XYz =getHaloBlock(Nxh-2*width,Nxh-width,Nyh-2*width,Nyh-width,width,2*width,dvcSendList_XYz);
sendCount_XYZ =getHaloBlock(Nxh-2*width,Nxh-width,Nyh-2*width,Nyh-width,Nzh-2*width,Nzh-width,dvcSendList_XYZ);
sendCount_xyz = getHaloBlock(width, 2 * width, width, 2 * width, width,
2 * width, dvcSendList_xyz);
sendCount_xyZ = getHaloBlock(width, 2 * width, width, 2 * width,
Nzh - 2 * width, Nzh - width, dvcSendList_xyZ);
sendCount_xYz = getHaloBlock(width, 2 * width, Nyh - 2 * width, Nyh - width,
width, 2 * width, dvcSendList_xYz);
sendCount_xYZ = getHaloBlock(width, 2 * width, Nyh - 2 * width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_xYZ);
sendCount_Xyz = getHaloBlock(Nxh - 2 * width, Nxh - width, width, 2 * width,
width, 2 * width, dvcSendList_Xyz);
sendCount_XyZ = getHaloBlock(Nxh - 2 * width, Nxh - width, width, 2 * width,
Nzh - 2 * width, Nzh - width, dvcSendList_XyZ);
sendCount_XYz =
getHaloBlock(Nxh - 2 * width, Nxh - width, Nyh - 2 * width, Nyh - width,
width, 2 * width, dvcSendList_XYz);
sendCount_XYZ =
getHaloBlock(Nxh - 2 * width, Nxh - width, Nyh - 2 * width, Nyh - width,
Nzh - 2 * width, Nzh - width, dvcSendList_XYZ);
/* Recv lists */
recvCount_x =getHaloBlock(0,width,width,Nyh-width,width,Nzh-width,dvcRecvList_x);
recvCount_X =getHaloBlock(Nxh-width,Nxh,width,Nyh-width,width,Nzh-width,dvcRecvList_X);
recvCount_y =getHaloBlock(width,Nxh-width,0,width,width,Nzh-width,dvcRecvList_y);
recvCount_Y =getHaloBlock(width,Nxh-width,Nyh-width,Nyh,width,Nzh-width,dvcRecvList_Y);
recvCount_z =getHaloBlock(width,Nxh-width,width,Nyh-width,0,width,dvcRecvList_z);
recvCount_Z =getHaloBlock(width,Nxh-width,width,Nyh-width,Nzh-width,Nzh,dvcRecvList_Z);
recvCount_x = getHaloBlock(0, width, width, Nyh - width, width, Nzh - width,
dvcRecvList_x);
recvCount_X = getHaloBlock(Nxh - width, Nxh, width, Nyh - width, width,
Nzh - width, dvcRecvList_X);
recvCount_y = getHaloBlock(width, Nxh - width, 0, width, width, Nzh - width,
dvcRecvList_y);
recvCount_Y = getHaloBlock(width, Nxh - width, Nyh - width, Nyh, width,
Nzh - width, dvcRecvList_Y);
recvCount_z = getHaloBlock(width, Nxh - width, width, Nyh - width, 0, width,
dvcRecvList_z);
recvCount_Z = getHaloBlock(width, Nxh - width, width, Nyh - width,
Nzh - width, Nzh, dvcRecvList_Z);
//xy
recvCount_xy =getHaloBlock(0,width,0,width,width,Nzh-width,dvcRecvList_xy);
recvCount_xY =getHaloBlock(0,width,Nyh-width,Nyh,width,Nzh-width,dvcRecvList_xY);
recvCount_Xy =getHaloBlock(Nxh-width,Nxh,0,width,width,Nzh-width,dvcRecvList_Xy);
recvCount_XY =getHaloBlock(Nxh-width,Nxh,Nyh-width,Nyh,width,Nzh-width,dvcRecvList_XY);
recvCount_xy =
getHaloBlock(0, width, 0, width, width, Nzh - width, dvcRecvList_xy);
recvCount_xY = getHaloBlock(0, width, Nyh - width, Nyh, width, Nzh - width,
dvcRecvList_xY);
recvCount_Xy = getHaloBlock(Nxh - width, Nxh, 0, width, width, Nzh - width,
dvcRecvList_Xy);
recvCount_XY = getHaloBlock(Nxh - width, Nxh, Nyh - width, Nyh, width,
Nzh - width, dvcRecvList_XY);
//xz
recvCount_xz =getHaloBlock(0,width,width,Nyh-width,0,width,dvcRecvList_xz);
recvCount_xZ =getHaloBlock(0,width,width,Nyh-width,Nzh-width,Nzh,dvcRecvList_xZ);
recvCount_Xz =getHaloBlock(Nxh-width,Nxh,width,Nyh-width,0,width,dvcRecvList_Xz);
recvCount_XZ =getHaloBlock(Nxh-width,Nxh,width,Nyh-width,Nzh-width,Nzh,dvcRecvList_XZ);
recvCount_xz =
getHaloBlock(0, width, width, Nyh - width, 0, width, dvcRecvList_xz);
recvCount_xZ = getHaloBlock(0, width, width, Nyh - width, Nzh - width, Nzh,
dvcRecvList_xZ);
recvCount_Xz = getHaloBlock(Nxh - width, Nxh, width, Nyh - width, 0, width,
dvcRecvList_Xz);
recvCount_XZ = getHaloBlock(Nxh - width, Nxh, width, Nyh - width,
Nzh - width, Nzh, dvcRecvList_XZ);
//yz
recvCount_yz =getHaloBlock(width,Nxh-width,0,width,0,width,dvcRecvList_yz);
recvCount_yZ =getHaloBlock(width,Nxh-width,0,width,Nzh-width,Nzh,dvcRecvList_yZ);
recvCount_Yz =getHaloBlock(width,Nxh-width,Nyh-width,Nyh,0,width,dvcRecvList_Yz);
recvCount_YZ =getHaloBlock(width,Nxh-width,Nyh-width,Nyh,Nzh-width,Nzh,dvcRecvList_YZ);
recvCount_yz =
getHaloBlock(width, Nxh - width, 0, width, 0, width, dvcRecvList_yz);
recvCount_yZ = getHaloBlock(width, Nxh - width, 0, width, Nzh - width, Nzh,
dvcRecvList_yZ);
recvCount_Yz = getHaloBlock(width, Nxh - width, Nyh - width, Nyh, 0, width,
dvcRecvList_Yz);
recvCount_YZ = getHaloBlock(width, Nxh - width, Nyh - width, Nyh,
Nzh - width, Nzh, dvcRecvList_YZ);
//xyz
recvCount_xyz = getHaloBlock(0, width, 0, width, 0, width, dvcRecvList_xyz);
recvCount_xyZ =getHaloBlock(0,width,0,width,Nzh-width,Nzh,dvcRecvList_xyZ);
recvCount_xYz =getHaloBlock(0,width,Nyh-width,Nyh,0,width,dvcRecvList_xYz);
recvCount_xYZ =getHaloBlock(0,width,Nyh-width,Nyh,Nzh-width,Nzh,dvcRecvList_xYZ);
recvCount_Xyz =getHaloBlock(Nxh-width,Nxh,0,width,0,width,dvcRecvList_Xyz);
recvCount_XyZ =getHaloBlock(Nxh-width,Nxh,0,width,Nzh-width,Nzh,dvcRecvList_XyZ);
recvCount_XYz =getHaloBlock(Nxh-width,Nxh,Nyh-width,Nyh,0,width,dvcRecvList_XYz);
recvCount_XYZ =getHaloBlock(Nxh-width,Nxh,Nyh-width,Nyh,Nzh-width,Nzh,dvcRecvList_XYZ);
recvCount_xyZ =
getHaloBlock(0, width, 0, width, Nzh - width, Nzh, dvcRecvList_xyZ);
recvCount_xYz =
getHaloBlock(0, width, Nyh - width, Nyh, 0, width, dvcRecvList_xYz);
recvCount_xYZ = getHaloBlock(0, width, Nyh - width, Nyh, Nzh - width, Nzh,
dvcRecvList_xYZ);
recvCount_Xyz =
getHaloBlock(Nxh - width, Nxh, 0, width, 0, width, dvcRecvList_Xyz);
recvCount_XyZ = getHaloBlock(Nxh - width, Nxh, 0, width, Nzh - width, Nzh,
dvcRecvList_XyZ);
recvCount_XYz = getHaloBlock(Nxh - width, Nxh, Nyh - width, Nyh, 0, width,
dvcRecvList_XYz);
recvCount_XYZ = getHaloBlock(Nxh - width, Nxh, Nyh - width, Nyh,
Nzh - width, Nzh, dvcRecvList_XYZ);
//......................................................................................
ScaLBL_AllocateZeroCopy((void **) &sendbuf_x, sendCount_x*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_X, sendCount_X*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_y, sendCount_y*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Y, sendCount_Y*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_z, sendCount_z*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Z, sendCount_Z*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xy, sendCount_xy*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xY, sendCount_xY*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Xy, sendCount_Xy*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XY, sendCount_XY*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xz, sendCount_xz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xZ, sendCount_xZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Xz, sendCount_Xz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XZ, sendCount_XZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_yz, sendCount_yz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_yZ, sendCount_yZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Yz, sendCount_Yz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_YZ, sendCount_YZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xyz, sendCount_xyz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xYz, sendCount_xYz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_Xyz, sendCount_Xyz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XYz, sendCount_XYz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xyZ, sendCount_xyZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_xYZ, sendCount_xYZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XyZ, sendCount_XyZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &sendbuf_XYZ, sendCount_XYZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_x,
sendCount_x *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_X,
sendCount_X *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_y,
sendCount_y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Y,
sendCount_Y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_z,
sendCount_z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Z,
sendCount_Z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xy,
sendCount_xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xY,
sendCount_xY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Xy,
sendCount_Xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XY,
sendCount_XY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xz,
sendCount_xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xZ,
sendCount_xZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Xz,
sendCount_Xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XZ,
sendCount_XZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_yz,
sendCount_yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_yZ,
sendCount_yZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Yz,
sendCount_Yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_YZ,
sendCount_YZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xyz,
sendCount_xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xYz,
sendCount_xYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_Xyz,
sendCount_Xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XYz,
sendCount_XYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xyZ,
sendCount_xyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_xYZ,
sendCount_xYZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XyZ,
sendCount_XyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&sendbuf_XYZ,
sendCount_XYZ *
sizeof(double)); // Allocate device memory
//......................................................................................
ScaLBL_AllocateZeroCopy((void **) &recvbuf_x, recvCount_x*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_X, recvCount_X*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_y, recvCount_y*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Y, recvCount_Y*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_z, recvCount_z*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Z, recvCount_Z*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xy, recvCount_xy*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xY, recvCount_xY*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Xy, recvCount_Xy*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XY, recvCount_XY*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xz, recvCount_xz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xZ, recvCount_xZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Xz, recvCount_Xz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XZ, recvCount_XZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_yz, recvCount_yz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_yZ, recvCount_yZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Yz, recvCount_Yz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_YZ, recvCount_YZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xyz, recvCount_xyz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xYz, recvCount_xYz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_Xyz, recvCount_Xyz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XYz, recvCount_XYz*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xyZ, recvCount_xyZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_xYZ, recvCount_xYZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XyZ, recvCount_XyZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **) &recvbuf_XYZ, recvCount_XYZ*sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_x,
recvCount_x *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_X,
recvCount_X *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_y,
recvCount_y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Y,
recvCount_Y *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_z,
recvCount_z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Z,
recvCount_Z *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xy,
recvCount_xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xY,
recvCount_xY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Xy,
recvCount_Xy *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XY,
recvCount_XY *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xz,
recvCount_xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xZ,
recvCount_xZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Xz,
recvCount_Xz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XZ,
recvCount_XZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_yz,
recvCount_yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_yZ,
recvCount_yZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Yz,
recvCount_Yz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_YZ,
recvCount_YZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xyz,
recvCount_xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xYz,
recvCount_xYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_Xyz,
recvCount_Xyz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XYz,
recvCount_XYz *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xyZ,
recvCount_xyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_xYZ,
recvCount_xYZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XyZ,
recvCount_XyZ *
sizeof(double)); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&recvbuf_XYZ,
recvCount_XYZ *
sizeof(double)); // Allocate device memory
/* Set up a map to the halo width=1 data structure */
for (k = width; k < Nzh - width; k++) {
@ -189,15 +349,14 @@ ScaLBLWideHalo_Communicator::ScaLBLWideHalo_Communicator(std::shared_ptr <Domain
}
}
}
}
void ScaLBLWideHalo_Communicator::Send(double *data) {
//...................................................................................
if (Lock == true) {
ERROR("ScaLBL Error (SendHalo): ScaLBLWideHalo_Communicator is locked -- did you forget to match Send/Recv calls?");
}
else{
ERROR("ScaLBL Error (SendHalo): ScaLBLWideHalo_Communicator is locked "
"-- did you forget to match Send/Recv calls?");
} else {
Lock = true;
}
ScaLBL_DeviceBarrier();
@ -234,67 +393,115 @@ void ScaLBLWideHalo_Communicator::Send(double *data){
//...................................................................................
// Send / Recv all the phase indcator field values
//...................................................................................
req1[0] = MPI_COMM_SCALBL.Isend(sendbuf_x,sendCount_x,rank_x,sendtag+0);
req2[0] = MPI_COMM_SCALBL.Irecv(recvbuf_X,recvCount_X,rank_X,recvtag+0);
req1[1] = MPI_COMM_SCALBL.Isend(sendbuf_X,sendCount_X,rank_X,sendtag+1);
req2[1] = MPI_COMM_SCALBL.Irecv(recvbuf_x,recvCount_x,rank_x,recvtag+1);
req1[2] = MPI_COMM_SCALBL.Isend(sendbuf_y,sendCount_y,rank_y,sendtag+2);
req2[2] = MPI_COMM_SCALBL.Irecv(recvbuf_Y,recvCount_Y,rank_Y,recvtag+2);
req1[3] = MPI_COMM_SCALBL.Isend(sendbuf_Y,sendCount_Y,rank_Y,sendtag+3);
req2[3] = MPI_COMM_SCALBL.Irecv(recvbuf_y,recvCount_y,rank_y,recvtag+3);
req1[4] = MPI_COMM_SCALBL.Isend(sendbuf_z,sendCount_z,rank_z,sendtag+4);
req2[4] = MPI_COMM_SCALBL.Irecv(recvbuf_Z,recvCount_Z,rank_Z,recvtag+4);
req1[5] = MPI_COMM_SCALBL.Isend(sendbuf_Z,sendCount_Z,rank_Z,sendtag+5);
req2[5] = MPI_COMM_SCALBL.Irecv(recvbuf_z,recvCount_z,rank_z,recvtag+5);
req1[6] = MPI_COMM_SCALBL.Isend(sendbuf_xy,sendCount_xy,rank_xy,sendtag+6);
req2[6] = MPI_COMM_SCALBL.Irecv(recvbuf_XY,recvCount_XY,rank_XY,recvtag+6);
req1[7] = MPI_COMM_SCALBL.Isend(sendbuf_XY,sendCount_XY,rank_XY,sendtag+7);
req2[7] = MPI_COMM_SCALBL.Irecv(recvbuf_xy,recvCount_xy,rank_xy,recvtag+7);
req1[8] = MPI_COMM_SCALBL.Isend(sendbuf_Xy,sendCount_Xy,rank_Xy,sendtag+8);
req2[8] = MPI_COMM_SCALBL.Irecv(recvbuf_xY,recvCount_xY,rank_xY,recvtag+8);
req1[9] = MPI_COMM_SCALBL.Isend(sendbuf_xY,sendCount_xY,rank_xY,sendtag+9);
req2[9] = MPI_COMM_SCALBL.Irecv(recvbuf_Xy,recvCount_Xy,rank_Xy,recvtag+9);
req1[10] = MPI_COMM_SCALBL.Isend(sendbuf_xz,sendCount_xz,rank_xz,sendtag+10);
req2[10] = MPI_COMM_SCALBL.Irecv(recvbuf_XZ,recvCount_XZ,rank_XZ,recvtag+10);
req1[11] = MPI_COMM_SCALBL.Isend(sendbuf_XZ,sendCount_XZ,rank_XZ,sendtag+11);
req2[11] = MPI_COMM_SCALBL.Irecv(recvbuf_xz,recvCount_xz,rank_xz,recvtag+11);
req1[12] = MPI_COMM_SCALBL.Isend(sendbuf_Xz,sendCount_Xz,rank_Xz,sendtag+12);
req2[12] = MPI_COMM_SCALBL.Irecv(recvbuf_xZ,recvCount_xZ,rank_xZ,recvtag+12);
req1[13] = MPI_COMM_SCALBL.Isend(sendbuf_xZ,sendCount_xZ,rank_xZ,sendtag+13);
req2[13] = MPI_COMM_SCALBL.Irecv(recvbuf_Xz,recvCount_Xz,rank_Xz,recvtag+13);
req1[14] = MPI_COMM_SCALBL.Isend(sendbuf_yz,sendCount_yz,rank_yz,sendtag+14);
req2[14] = MPI_COMM_SCALBL.Irecv(recvbuf_YZ,recvCount_YZ,rank_YZ,recvtag+14);
req1[15] = MPI_COMM_SCALBL.Isend(sendbuf_YZ,sendCount_YZ,rank_YZ,sendtag+15);
req2[15] = MPI_COMM_SCALBL.Irecv(recvbuf_yz,recvCount_yz,rank_yz,recvtag+15);
req1[16] = MPI_COMM_SCALBL.Isend(sendbuf_Yz,sendCount_Yz,rank_Yz,sendtag+16);
req2[16] = MPI_COMM_SCALBL.Irecv(recvbuf_yZ,recvCount_yZ,rank_yZ,recvtag+16);
req1[17] = MPI_COMM_SCALBL.Isend(sendbuf_yZ,sendCount_yZ,rank_yZ,sendtag+17);
req2[17] = MPI_COMM_SCALBL.Irecv(recvbuf_Yz,recvCount_Yz,rank_Yz,recvtag+17);
req1[0] =
MPI_COMM_SCALBL.Isend(sendbuf_x, sendCount_x, rank_x, sendtag + 0);
req2[0] =
MPI_COMM_SCALBL.Irecv(recvbuf_X, recvCount_X, rank_X, recvtag + 0);
req1[1] =
MPI_COMM_SCALBL.Isend(sendbuf_X, sendCount_X, rank_X, sendtag + 1);
req2[1] =
MPI_COMM_SCALBL.Irecv(recvbuf_x, recvCount_x, rank_x, recvtag + 1);
req1[2] =
MPI_COMM_SCALBL.Isend(sendbuf_y, sendCount_y, rank_y, sendtag + 2);
req2[2] =
MPI_COMM_SCALBL.Irecv(recvbuf_Y, recvCount_Y, rank_Y, recvtag + 2);
req1[3] =
MPI_COMM_SCALBL.Isend(sendbuf_Y, sendCount_Y, rank_Y, sendtag + 3);
req2[3] =
MPI_COMM_SCALBL.Irecv(recvbuf_y, recvCount_y, rank_y, recvtag + 3);
req1[4] =
MPI_COMM_SCALBL.Isend(sendbuf_z, sendCount_z, rank_z, sendtag + 4);
req2[4] =
MPI_COMM_SCALBL.Irecv(recvbuf_Z, recvCount_Z, rank_Z, recvtag + 4);
req1[5] =
MPI_COMM_SCALBL.Isend(sendbuf_Z, sendCount_Z, rank_Z, sendtag + 5);
req2[5] =
MPI_COMM_SCALBL.Irecv(recvbuf_z, recvCount_z, rank_z, recvtag + 5);
req1[6] =
MPI_COMM_SCALBL.Isend(sendbuf_xy, sendCount_xy, rank_xy, sendtag + 6);
req2[6] =
MPI_COMM_SCALBL.Irecv(recvbuf_XY, recvCount_XY, rank_XY, recvtag + 6);
req1[7] =
MPI_COMM_SCALBL.Isend(sendbuf_XY, sendCount_XY, rank_XY, sendtag + 7);
req2[7] =
MPI_COMM_SCALBL.Irecv(recvbuf_xy, recvCount_xy, rank_xy, recvtag + 7);
req1[8] =
MPI_COMM_SCALBL.Isend(sendbuf_Xy, sendCount_Xy, rank_Xy, sendtag + 8);
req2[8] =
MPI_COMM_SCALBL.Irecv(recvbuf_xY, recvCount_xY, rank_xY, recvtag + 8);
req1[9] =
MPI_COMM_SCALBL.Isend(sendbuf_xY, sendCount_xY, rank_xY, sendtag + 9);
req2[9] =
MPI_COMM_SCALBL.Irecv(recvbuf_Xy, recvCount_Xy, rank_Xy, recvtag + 9);
req1[10] =
MPI_COMM_SCALBL.Isend(sendbuf_xz, sendCount_xz, rank_xz, sendtag + 10);
req2[10] =
MPI_COMM_SCALBL.Irecv(recvbuf_XZ, recvCount_XZ, rank_XZ, recvtag + 10);
req1[11] =
MPI_COMM_SCALBL.Isend(sendbuf_XZ, sendCount_XZ, rank_XZ, sendtag + 11);
req2[11] =
MPI_COMM_SCALBL.Irecv(recvbuf_xz, recvCount_xz, rank_xz, recvtag + 11);
req1[12] =
MPI_COMM_SCALBL.Isend(sendbuf_Xz, sendCount_Xz, rank_Xz, sendtag + 12);
req2[12] =
MPI_COMM_SCALBL.Irecv(recvbuf_xZ, recvCount_xZ, rank_xZ, recvtag + 12);
req1[13] =
MPI_COMM_SCALBL.Isend(sendbuf_xZ, sendCount_xZ, rank_xZ, sendtag + 13);
req2[13] =
MPI_COMM_SCALBL.Irecv(recvbuf_Xz, recvCount_Xz, rank_Xz, recvtag + 13);
req1[14] =
MPI_COMM_SCALBL.Isend(sendbuf_yz, sendCount_yz, rank_yz, sendtag + 14);
req2[14] =
MPI_COMM_SCALBL.Irecv(recvbuf_YZ, recvCount_YZ, rank_YZ, recvtag + 14);
req1[15] =
MPI_COMM_SCALBL.Isend(sendbuf_YZ, sendCount_YZ, rank_YZ, sendtag + 15);
req2[15] =
MPI_COMM_SCALBL.Irecv(recvbuf_yz, recvCount_yz, rank_yz, recvtag + 15);
req1[16] =
MPI_COMM_SCALBL.Isend(sendbuf_Yz, sendCount_Yz, rank_Yz, sendtag + 16);
req2[16] =
MPI_COMM_SCALBL.Irecv(recvbuf_yZ, recvCount_yZ, rank_yZ, recvtag + 16);
req1[17] =
MPI_COMM_SCALBL.Isend(sendbuf_yZ, sendCount_yZ, rank_yZ, sendtag + 17);
req2[17] =
MPI_COMM_SCALBL.Irecv(recvbuf_Yz, recvCount_Yz, rank_Yz, recvtag + 17);
/* Corners */
req1[18] = MPI_COMM_SCALBL.Isend(sendbuf_xyz,sendCount_xyz,rank_xyz,sendtag+18);
req2[18] = MPI_COMM_SCALBL.Irecv(recvbuf_XYZ,recvCount_XYZ,rank_XYZ,recvtag+18);
req1[19] = MPI_COMM_SCALBL.Isend(sendbuf_XYz,sendCount_XYz,rank_XYz,sendtag+19);
req2[19] = MPI_COMM_SCALBL.Irecv(recvbuf_xyZ,recvCount_xyZ,rank_xyZ,recvtag+19);
req1[20] = MPI_COMM_SCALBL.Isend(sendbuf_Xyz,sendCount_Xyz,rank_Xyz,sendtag+20);
req2[20] = MPI_COMM_SCALBL.Irecv(recvbuf_xYZ,recvCount_xYZ,rank_xYZ,recvtag+20);
req1[21] = MPI_COMM_SCALBL.Isend(sendbuf_xYz,sendCount_xYz,rank_xYz,sendtag+21);
req2[21] = MPI_COMM_SCALBL.Irecv(recvbuf_XyZ,recvCount_XyZ,rank_XyZ,recvtag+21);
req1[22] = MPI_COMM_SCALBL.Isend(sendbuf_xyZ,sendCount_xyZ,rank_xyZ,sendtag+22);
req2[22] = MPI_COMM_SCALBL.Irecv(recvbuf_XYz,recvCount_XYz,rank_XYz,recvtag+22);
req1[23] = MPI_COMM_SCALBL.Isend(sendbuf_XYZ,sendCount_XYZ,rank_XYZ,sendtag+23);
req2[23] = MPI_COMM_SCALBL.Irecv(recvbuf_xyz,recvCount_xyz,rank_xyz,recvtag+23);
req1[24] = MPI_COMM_SCALBL.Isend(sendbuf_XyZ,sendCount_XyZ,rank_XyZ,sendtag+24);
req2[24] = MPI_COMM_SCALBL.Irecv(recvbuf_xYz,recvCount_xYz,rank_xYz,recvtag+24);
req1[25] = MPI_COMM_SCALBL.Isend(sendbuf_xYZ,sendCount_xYZ,rank_xYZ,sendtag+25);
req2[25] = MPI_COMM_SCALBL.Irecv(recvbuf_Xyz,recvCount_Xyz,rank_Xyz,recvtag+25);
req1[18] = MPI_COMM_SCALBL.Isend(sendbuf_xyz, sendCount_xyz, rank_xyz,
sendtag + 18);
req2[18] = MPI_COMM_SCALBL.Irecv(recvbuf_XYZ, recvCount_XYZ, rank_XYZ,
recvtag + 18);
req1[19] = MPI_COMM_SCALBL.Isend(sendbuf_XYz, sendCount_XYz, rank_XYz,
sendtag + 19);
req2[19] = MPI_COMM_SCALBL.Irecv(recvbuf_xyZ, recvCount_xyZ, rank_xyZ,
recvtag + 19);
req1[20] = MPI_COMM_SCALBL.Isend(sendbuf_Xyz, sendCount_Xyz, rank_Xyz,
sendtag + 20);
req2[20] = MPI_COMM_SCALBL.Irecv(recvbuf_xYZ, recvCount_xYZ, rank_xYZ,
recvtag + 20);
req1[21] = MPI_COMM_SCALBL.Isend(sendbuf_xYz, sendCount_xYz, rank_xYz,
sendtag + 21);
req2[21] = MPI_COMM_SCALBL.Irecv(recvbuf_XyZ, recvCount_XyZ, rank_XyZ,
recvtag + 21);
req1[22] = MPI_COMM_SCALBL.Isend(sendbuf_xyZ, sendCount_xyZ, rank_xyZ,
sendtag + 22);
req2[22] = MPI_COMM_SCALBL.Irecv(recvbuf_XYz, recvCount_XYz, rank_XYz,
recvtag + 22);
req1[23] = MPI_COMM_SCALBL.Isend(sendbuf_XYZ, sendCount_XYZ, rank_XYZ,
sendtag + 23);
req2[23] = MPI_COMM_SCALBL.Irecv(recvbuf_xyz, recvCount_xyz, rank_xyz,
recvtag + 23);
req1[24] = MPI_COMM_SCALBL.Isend(sendbuf_XyZ, sendCount_XyZ, rank_XyZ,
sendtag + 24);
req2[24] = MPI_COMM_SCALBL.Irecv(recvbuf_xYz, recvCount_xYz, rank_xYz,
recvtag + 24);
req1[25] = MPI_COMM_SCALBL.Isend(sendbuf_xYZ, sendCount_xYZ, rank_xYZ,
sendtag + 25);
req2[25] = MPI_COMM_SCALBL.Irecv(recvbuf_Xyz, recvCount_Xyz, rank_Xyz,
recvtag + 25);
//...................................................................................
}
ScaLBLWideHalo_Communicator::~ScaLBLWideHalo_Communicator()
{
}
ScaLBLWideHalo_Communicator::~ScaLBLWideHalo_Communicator() {}
void ScaLBLWideHalo_Communicator::Recv(double *data) {
//...................................................................................
@ -335,6 +542,4 @@ void ScaLBLWideHalo_Communicator::Recv(double *data){
//...................................................................................
Lock = false; // unlock the communicator after communications complete
//...................................................................................
}

View File

@ -23,14 +23,20 @@ public:
// Set up for D3Q19 distributions -- all 27 neighbors are needed
//......................................................................................
// Buffers to store data sent and recieved by this MPI process
double *sendbuf_x, *sendbuf_y, *sendbuf_z, *sendbuf_X, *sendbuf_Y, *sendbuf_Z;
double *sendbuf_xy, *sendbuf_yz, *sendbuf_xz, *sendbuf_Xy, *sendbuf_Yz, *sendbuf_xZ;
double *sendbuf_xY, *sendbuf_yZ, *sendbuf_Xz, *sendbuf_XY, *sendbuf_YZ, *sendbuf_XZ;
double *sendbuf_x, *sendbuf_y, *sendbuf_z, *sendbuf_X, *sendbuf_Y,
*sendbuf_Z;
double *sendbuf_xy, *sendbuf_yz, *sendbuf_xz, *sendbuf_Xy, *sendbuf_Yz,
*sendbuf_xZ;
double *sendbuf_xY, *sendbuf_yZ, *sendbuf_Xz, *sendbuf_XY, *sendbuf_YZ,
*sendbuf_XZ;
double *sendbuf_xyz, *sendbuf_Xyz, *sendbuf_xYz, *sendbuf_XYz;
double *sendbuf_xyZ, *sendbuf_XyZ, *sendbuf_xYZ, *sendbuf_XYZ;
double *recvbuf_x, *recvbuf_y, *recvbuf_z, *recvbuf_X, *recvbuf_Y, *recvbuf_Z;
double *recvbuf_xy, *recvbuf_yz, *recvbuf_xz, *recvbuf_Xy, *recvbuf_Yz, *recvbuf_xZ;
double *recvbuf_xY, *recvbuf_yZ, *recvbuf_Xz, *recvbuf_XY, *recvbuf_YZ, *recvbuf_XZ;
double *recvbuf_x, *recvbuf_y, *recvbuf_z, *recvbuf_X, *recvbuf_Y,
*recvbuf_Z;
double *recvbuf_xy, *recvbuf_yz, *recvbuf_xz, *recvbuf_Xy, *recvbuf_Yz,
*recvbuf_xZ;
double *recvbuf_xY, *recvbuf_yZ, *recvbuf_Xz, *recvbuf_XY, *recvbuf_YZ,
*recvbuf_XZ;
double *recvbuf_xyz, *recvbuf_Xyz, *recvbuf_xYz, *recvbuf_XYz;
double *recvbuf_xyZ, *recvbuf_XyZ, *recvbuf_xYZ, *recvbuf_XYZ;
//......................................................................................
@ -45,7 +51,8 @@ public:
void PrintDebug();
private:
bool Lock; // use Lock to make sure only one call at a time to protect data in transit
bool
Lock; // use Lock to make sure only one call at a time to protect data in transit
// only one set of Send requests can be active at any time (per instance)
int i, j, k, n;
int iproc, jproc, kproc;
@ -68,33 +75,46 @@ private:
int rank_xyZ, rank_XyZ, rank_xYZ, rank_XYZ;
//......................................................................................
//......................................................................................
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y, sendCount_Z;
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz, sendCount_xZ;
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ, sendCount_XZ;
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y,
sendCount_Z;
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz,
sendCount_xZ;
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ,
sendCount_XZ;
int sendCount_xyz, sendCount_Xyz, sendCount_xYz, sendCount_XYz;
int sendCount_xyZ, sendCount_XyZ, sendCount_xYZ, sendCount_XYZ;
//......................................................................................
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y, recvCount_Z;
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz, recvCount_xZ;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ, recvCount_XZ;
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y,
recvCount_Z;
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz,
recvCount_xZ;
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ,
recvCount_XZ;
int recvCount_xyz, recvCount_Xyz, recvCount_xYz, recvCount_XYz;
int recvCount_xyZ, recvCount_XyZ, recvCount_xYZ, recvCount_XYZ;
//......................................................................................
// Send buffers that reside on the compute device
int *dvcSendList_x, *dvcSendList_y, *dvcSendList_z, *dvcSendList_X, *dvcSendList_Y, *dvcSendList_Z;
int *dvcSendList_xy, *dvcSendList_yz, *dvcSendList_xz, *dvcSendList_Xy, *dvcSendList_Yz, *dvcSendList_xZ;
int *dvcSendList_xY, *dvcSendList_yZ, *dvcSendList_Xz, *dvcSendList_XY, *dvcSendList_YZ, *dvcSendList_XZ;
int *dvcSendList_x, *dvcSendList_y, *dvcSendList_z, *dvcSendList_X,
*dvcSendList_Y, *dvcSendList_Z;
int *dvcSendList_xy, *dvcSendList_yz, *dvcSendList_xz, *dvcSendList_Xy,
*dvcSendList_Yz, *dvcSendList_xZ;
int *dvcSendList_xY, *dvcSendList_yZ, *dvcSendList_Xz, *dvcSendList_XY,
*dvcSendList_YZ, *dvcSendList_XZ;
int *dvcSendList_xyz, *dvcSendList_Xyz, *dvcSendList_xYz, *dvcSendList_XYz;
int *dvcSendList_xyZ, *dvcSendList_XyZ, *dvcSendList_xYZ, *dvcSendList_XYZ;
// Recieve buffers that reside on the compute device
int *dvcRecvList_x, *dvcRecvList_y, *dvcRecvList_z, *dvcRecvList_X, *dvcRecvList_Y, *dvcRecvList_Z;
int *dvcRecvList_xy, *dvcRecvList_yz, *dvcRecvList_xz, *dvcRecvList_Xy, *dvcRecvList_Yz, *dvcRecvList_xZ;
int *dvcRecvList_xY, *dvcRecvList_yZ, *dvcRecvList_Xz, *dvcRecvList_XY, *dvcRecvList_YZ, *dvcRecvList_XZ;
int *dvcRecvList_x, *dvcRecvList_y, *dvcRecvList_z, *dvcRecvList_X,
*dvcRecvList_Y, *dvcRecvList_Z;
int *dvcRecvList_xy, *dvcRecvList_yz, *dvcRecvList_xz, *dvcRecvList_Xy,
*dvcRecvList_Yz, *dvcRecvList_xZ;
int *dvcRecvList_xY, *dvcRecvList_yZ, *dvcRecvList_Xz, *dvcRecvList_XY,
*dvcRecvList_YZ, *dvcRecvList_XZ;
int *dvcRecvList_xyz, *dvcRecvList_Xyz, *dvcRecvList_xYz, *dvcRecvList_XYz;
int *dvcRecvList_xyZ, *dvcRecvList_XyZ, *dvcRecvList_xYZ, *dvcRecvList_XYZ;
//......................................................................................
inline int getHaloBlock(int imin, int imax, int jmin, int jmax, int kmin, int kmax, int *& dvcList){
inline int getHaloBlock(int imin, int imax, int jmin, int jmax, int kmin,
int kmax, int *&dvcList) {
int count = 0;
int *List;
List = new int[(imax - imin) * (jmax - jmin) * (kmax - kmin)];
@ -106,10 +126,10 @@ private:
}
}
size_t numbytes = count * sizeof(int);
ScaLBL_AllocateZeroCopy((void **) &dvcList, numbytes); // Allocate device memory
ScaLBL_AllocateZeroCopy((void **)&dvcList,
numbytes); // Allocate device memory
ScaLBL_CopyToZeroCopy(dvcList, List, numbytes);
return count;
}
};
#endif

View File

@ -1,8 +1,27 @@
extern "C" void ScaLBL_D3Q19_AAeven_BGK(double *dist, int start, int finish, int Np, double rlx, double Fx, double Fy, double Fz){
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
extern "C" void ScaLBL_D3Q19_AAeven_BGK(double *dist, int start, int finish,
int Np, double rlx, double Fx,
double Fy, double Fz) {
// conserved momemnts
double rho, ux, uy, uz, uu;
// non-conserved moments
double f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18;
double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18;
for (int n = start; n < finish; n++) {
// q=0
@ -26,7 +45,8 @@ extern "C" void ScaLBL_D3Q19_AAeven_BGK(double *dist, int start, int finish, int
f17 = dist[18 * Np + n];
f18 = dist[17 * Np + n];
rho = f0+f2+f1+f4+f3+f6+f5+f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18+f17;
rho = f0 + f2 + f1 + f4 + f3 + f6 + f5 + f8 + f7 + f10 + f9 + f12 +
f11 + f14 + f13 + f16 + f15 + f18 + f17;
ux = f1 - f2 + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
uy = f3 - f4 + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
uz = f5 - f6 + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
@ -36,85 +56,140 @@ extern "C" void ScaLBL_D3Q19_AAeven_BGK(double *dist, int start, int finish, int
dist[n] = f0 * (1.0 - rlx) + rlx * 0.3333333333333333 * (1.0 - uu);
// q = 1
dist[1*Np+n] = f1*(1.0-rlx) + rlx*0.05555555555555555*(rho + 3.0*ux + 4.5*ux*ux - uu) + 0.16666666*Fx;
dist[1 * Np + n] =
f1 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * ux + 4.5 * ux * ux - uu) +
0.16666666 * Fx;
// q=2
dist[2*Np+n] = f2*(1.0-rlx) + rlx*0.05555555555555555*(rho - 3.0*ux + 4.5*ux*ux - uu)- 0.16666666*Fx;
dist[2 * Np + n] =
f2 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * ux + 4.5 * ux * ux - uu) -
0.16666666 * Fx;
// q = 3
dist[3*Np+n] = f3*(1.0-rlx) +
rlx*0.05555555555555555*(rho + 3.0*uy + 4.5*uy*uy - uu) + 0.16666666*Fy;
dist[3 * Np + n] =
f3 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uy + 4.5 * uy * uy - uu) +
0.16666666 * Fy;
// q = 4
dist[4*Np+n] = f4*(1.0-rlx) +
rlx*0.05555555555555555*(rho - 3.0*uy + 4.5*uy*uy - uu)- 0.16666666*Fy;
dist[4 * Np + n] =
f4 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uy + 4.5 * uy * uy - uu) -
0.16666666 * Fy;
// q = 5
dist[5*Np+n] = f5*(1.0-rlx) +
rlx*0.05555555555555555*(rho + 3.0*uz + 4.5*uz*uz - uu) + 0.16666666*Fz;
dist[5 * Np + n] =
f5 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uz + 4.5 * uz * uz - uu) +
0.16666666 * Fz;
// q = 6
dist[6*Np+n] = f6*(1.0-rlx) +
rlx*0.05555555555555555*(rho - 3.0*uz + 4.5*uz*uz - uu) - 0.16666666*Fz;
dist[6 * Np + n] =
f6 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uz + 4.5 * uz * uz - uu) -
0.16666666 * Fz;
// q = 7
dist[7*Np+n] = f7*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) + 0.08333333333*(Fx+Fy);
dist[7 * Np + n] =
f7 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) +
0.08333333333 * (Fx + Fy);
// q = 8
dist[8*Np+n] = f8*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) - 0.08333333333*(Fx+Fy);
dist[8 * Np + n] =
f8 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) -
0.08333333333 * (Fx + Fy);
// q = 9
dist[9*Np+n] = f9*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) + 0.08333333333*(Fx-Fy);
dist[9 * Np + n] =
f9 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) +
0.08333333333 * (Fx - Fy);
// q = 10
dist[10*Np+n] = f10*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) - 0.08333333333*(Fx-Fy);
dist[10 * Np + n] =
f10 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) -
0.08333333333 * (Fx - Fy);
// q = 11
dist[11*Np+n] = f11*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) + 0.08333333333*(Fx+Fz);
dist[11 * Np + n] =
f11 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) +
0.08333333333 * (Fx + Fz);
// q = 12
dist[12*Np+n] = f12*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) - 0.08333333333*(Fx+Fz);
dist[12 * Np + n] =
f12 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) -
0.08333333333 * (Fx + Fz);
// q = 13
dist[13*Np+n] = f13*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu) + 0.08333333333*(Fx-Fz);
dist[13 * Np + n] =
f13 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) +
0.08333333333 * (Fx - Fz);
// q= 14
dist[14*Np+n] = f14*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu)- 0.08333333333*(Fx-Fz);
dist[14 * Np + n] =
f14 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) -
0.08333333333 * (Fx - Fz);
// q = 15
dist[15*Np+n] = f15*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) + 0.08333333333*(Fy+Fz);
dist[15 * Np + n] =
f15 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) +
0.08333333333 * (Fy + Fz);
// q = 16
dist[16*Np+n] = f16*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) - 0.08333333333*(Fy+Fz);
dist[16 * Np + n] =
f16 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) -
0.08333333333 * (Fy + Fz);
// q = 17
dist[17*Np+n] = f17*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) + 0.08333333333*(Fy-Fz);
dist[17 * Np + n] =
f17 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) +
0.08333333333 * (Fy - Fz);
// q = 18
dist[18*Np+n] = f18*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) - 0.08333333333*(Fy-Fz);
dist[18 * Np + n] =
f18 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) -
0.08333333333 * (Fy - Fz);
//........................................................................
}
}
extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist, int start, int finish, int Np, double rlx, double Fx, double Fy, double Fz){
extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist,
int start, int finish, int Np,
double rlx, double Fx, double Fy,
double Fz) {
// conserved momemnts
double rho, ux, uy, uz, uu;
// non-conserved moments
double f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18;
int nr1,nr2,nr3,nr4,nr5,nr6,nr7,nr8,nr9,nr10,nr11,nr12,nr13,nr14,nr15,nr16,nr17,nr18;
double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18;
int nr1, nr2, nr3, nr4, nr5, nr6, nr7, nr8, nr9, nr10, nr11, nr12, nr13,
nr14, nr15, nr16, nr17, nr18;
for (int n = start; n < finish; n++) {
@ -192,7 +267,8 @@ extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist, int star
nr18 = neighborList[n + 17 * Np];
f18 = dist[nr18];
rho = f0+f2+f1+f4+f3+f6+f5+f8+f7+f10+f9+f12+f11+f14+f13+f16+f15+f18+f17;
rho = f0 + f2 + f1 + f4 + f3 + f6 + f5 + f8 + f7 + f10 + f9 + f12 +
f11 + f14 + f13 + f16 + f15 + f18 + f17;
ux = f1 - f2 + f7 - f8 + f9 - f10 + f11 - f12 + f13 - f14;
uy = f3 - f4 + f7 - f8 - f9 + f10 + f15 - f16 + f17 - f18;
uz = f5 - f6 + f11 - f12 - f13 + f14 + f15 - f16 - f17 + f18;
@ -202,74 +278,123 @@ extern "C" void ScaLBL_D3Q19_AAodd_BGK(int *neighborList, double *dist, int star
dist[n] = f0 * (1.0 - rlx) + rlx * 0.3333333333333333 * (1.0 - uu);
// q = 1
dist[nr2] = f1*(1.0-rlx) + rlx*0.05555555555555555*(rho + 3.0*ux + 4.5*ux*ux - uu) + 0.16666666*Fx;
dist[nr2] =
f1 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * ux + 4.5 * ux * ux - uu) +
0.16666666 * Fx;
// q=2
dist[nr1] = f2*(1.0-rlx) + rlx*0.05555555555555555*(rho - 3.0*ux + 4.5*ux*ux - uu)- 0.16666666*Fx;
dist[nr1] =
f2 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * ux + 4.5 * ux * ux - uu) -
0.16666666 * Fx;
// q = 3
dist[nr4] = f3*(1.0-rlx) +
rlx*0.05555555555555555*(rho + 3.0*uy + 4.5*uy*uy - uu) + 0.16666666*Fy;
dist[nr4] =
f3 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uy + 4.5 * uy * uy - uu) +
0.16666666 * Fy;
// q = 4
dist[nr3] = f4*(1.0-rlx) +
rlx*0.05555555555555555*(rho - 3.0*uy + 4.5*uy*uy - uu)- 0.16666666*Fy;
dist[nr3] =
f4 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uy + 4.5 * uy * uy - uu) -
0.16666666 * Fy;
// q = 5
dist[nr6] = f5*(1.0-rlx) +
rlx*0.05555555555555555*(rho + 3.0*uz + 4.5*uz*uz - uu) + 0.16666666*Fz;
dist[nr6] =
f5 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho + 3.0 * uz + 4.5 * uz * uz - uu) +
0.16666666 * Fz;
// q = 6
dist[nr5] = f6*(1.0-rlx) +
rlx*0.05555555555555555*(rho - 3.0*uz + 4.5*uz*uz - uu) - 0.16666666*Fz;
dist[nr5] =
f6 * (1.0 - rlx) +
rlx * 0.05555555555555555 * (rho - 3.0 * uz + 4.5 * uz * uz - uu) -
0.16666666 * Fz;
// q = 7
dist[nr8] = f7*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) + 0.08333333333*(Fx+Fy);
dist[nr8] =
f7 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) +
0.08333333333 * (Fx + Fy);
// q = 8
dist[nr7] = f8*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux+uy) + 4.5*(ux+uy)*(ux+uy) - uu) - 0.08333333333*(Fx+Fy);
dist[nr7] =
f8 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uy) + 4.5 * (ux + uy) * (ux + uy) - uu) -
0.08333333333 * (Fx + Fy);
// q = 9
dist[nr10] = f9*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) + 0.08333333333*(Fx-Fy);
dist[nr10] =
f9 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) +
0.08333333333 * (Fx - Fy);
// q = 10
dist[nr9] = f10*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux-uy) + 4.5*(ux-uy)*(ux-uy) - uu) - 0.08333333333*(Fx-Fy);
dist[nr9] =
f10 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uy) + 4.5 * (ux - uy) * (ux - uy) - uu) -
0.08333333333 * (Fx - Fy);
// q = 11
dist[nr12] = f11*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) + 0.08333333333*(Fx+Fz);
dist[nr12] =
f11 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) +
0.08333333333 * (Fx + Fz);
// q = 12
dist[nr11] = f12*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux+uz) + 4.5*(ux+uz)*(ux+uz) - uu) - 0.08333333333*(Fx+Fz);
dist[nr11] =
f12 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux + uz) + 4.5 * (ux + uz) * (ux + uz) - uu) -
0.08333333333 * (Fx + Fz);
// q = 13
dist[nr14] = f13*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu) + 0.08333333333*(Fx-Fz);
dist[nr14] =
f13 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) +
0.08333333333 * (Fx - Fz);
// q= 14
dist[nr13] = f14*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(ux-uz) + 4.5*(ux-uz)*(ux-uz) - uu)- 0.08333333333*(Fx-Fz);
dist[nr13] =
f14 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (ux - uz) + 4.5 * (ux - uz) * (ux - uz) - uu) -
0.08333333333 * (Fx - Fz);
// q = 15
dist[nr16] = f15*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) + 0.08333333333*(Fy+Fz);
dist[nr16] =
f15 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) +
0.08333333333 * (Fy + Fz);
// q = 16
dist[nr15] = f16*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(uy+uz) + 4.5*(uy+uz)*(uy+uz) - uu) - 0.08333333333*(Fy+Fz);
dist[nr15] =
f16 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy + uz) + 4.5 * (uy + uz) * (uy + uz) - uu) -
0.08333333333 * (Fy + Fz);
// q = 17
dist[nr18] = f17*(1.0-rlx) +
rlx*0.02777777777777778*(rho + 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) + 0.08333333333*(Fy-Fz);
dist[nr18] =
f17 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho + 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) +
0.08333333333 * (Fy - Fz);
// q = 18
dist[nr17] = f18*(1.0-rlx) +
rlx*0.02777777777777778*(rho - 3.0*(uy-uz) + 4.5*(uy-uz)*(uy-uz) - uu) - 0.08333333333*(Fy-Fz);
dist[nr17] =
f18 * (1.0 - rlx) +
rlx * 0.02777777777777778 *
(rho - 3.0 * (uy - uz) + 4.5 * (uy - uz) * (uy - uz) - uu) -
0.08333333333 * (Fy - Fz);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,23 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
extern "C" void ScaLBL_D3Q19_Pack(int q, int *list, int start, int count, double *sendbuf, double *dist, int N){
extern "C" void ScaLBL_D3Q19_Pack(int q, int *list, int start, int count,
double *sendbuf, double *dist, int N) {
//....................................................................................
// Pack distribution q into the send buffer for the listed lattice sites
// dist may be even or odd distributions stored by stream layout
@ -25,14 +42,13 @@ extern "C" void ScaLBL_D3Q19_Unpack(int q, int *list, int start, int count,
// Get the value from the list -- note that n is the index is from the send (non-local) process
n = list[start + idx];
// unpack the distribution to the proper location
if (!(n<0)) dist[q*N+n] = recvbuf[start+idx];
if (!(n < 0))
dist[q * N + n] = recvbuf[start + idx];
//dist[q*N+n] = recvbuf[start+idx];
}
}
extern "C" void ScaLBL_D3Q19_AA_Init(double *f_even, double *f_odd, int Np)
{
extern "C" void ScaLBL_D3Q19_AA_Init(double *f_even, double *f_odd, int Np) {
int n;
for (n = 0; n < Np; n++) {
f_even[n] = 0.3333333333333333;
@ -54,12 +70,10 @@ extern "C" void ScaLBL_D3Q19_AA_Init(double *f_even, double *f_odd, int Np)
f_even[8 * Np + n] = 0.0277777777777778; //double(100*n)+16.f;
f_odd[8 * Np + n] = 0.0277777777777778; //double(100*n)+17.f;
f_even[9 * Np + n] = 0.0277777777777778; //double(100*n)+18.f;
}
}
extern "C" void ScaLBL_D3Q19_Init(double *dist, int Np)
{
extern "C" void ScaLBL_D3Q19_Init(double *dist, int Np) {
int n;
for (n = 0; n < Np; n++) {
dist[n] = 0.3333333333333333;
@ -85,8 +99,8 @@ extern "C" void ScaLBL_D3Q19_Init(double *dist, int Np)
}
//*************************************************************************
extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, int Nx, int Ny, int Nz)
{
extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd,
int Nx, int Ny, int Nz) {
int i, j, k, n, nn, N;
// distributions
double f1, f2, f3, f4, f5, f6, f7, f8, f9;
@ -119,7 +133,8 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
// Retrieve odd distributions from neighboring nodes (swap convention)
//........................................................................
nn = n + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary
if (!(i + 1 < Nx))
nn -= Nx; // periodic BC along the x-boundary
//if (i+1<Nx){
f2 = disteven[N + nn]; // pull neighbor for distribution 2
if (f2 > 0) {
@ -129,7 +144,8 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
//}
//........................................................................
nn = n + Nx; // neighbor index (pull convention)
if (!(j+1<Ny)) nn -= Nx*Ny; // Perioidic BC along the y-boundary
if (!(j + 1 < Ny))
nn -= Nx * Ny; // Perioidic BC along the y-boundary
//if (j+1<Ny){
f4 = disteven[2 * N + nn]; // pull neighbor for distribution 4
if (f4 > 0) {
@ -139,7 +155,8 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n + Nx * Ny; // neighbor index (pull convention)
if (!(k+1<Nz)) nn -= Nx*Ny*Nz; // Perioidic BC along the z-boundary
if (!(k + 1 < Nz))
nn -= Nx * Ny * Nz; // Perioidic BC along the z-boundary
//if (k+1<Nz){
f6 = disteven[3 * N + nn]; // pull neighbor for distribution 6
if (f6 > 0) {
@ -149,8 +166,10 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n + Nx + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary
if (!(j+1<Ny)) nn -= Nx*Ny; // Perioidic BC along the y-boundary
if (!(i + 1 < Nx))
nn -= Nx; // periodic BC along the x-boundary
if (!(j + 1 < Ny))
nn -= Nx * Ny; // Perioidic BC along the y-boundary
//if ((i+1<Nx) && (j+1<Ny)){
f8 = disteven[4 * N + nn]; // pull neighbor for distribution 8
if (f8 > 0) {
@ -160,8 +179,10 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n - Nx + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary
if (j-1<0) nn += Nx*Ny; // Perioidic BC along the y-boundary
if (!(i + 1 < Nx))
nn -= Nx; // periodic BC along the x-boundary
if (j - 1 < 0)
nn += Nx * Ny; // Perioidic BC along the y-boundary
//if (!(i-1<0) && (j+1<Ny)){
f10 = disteven[5 * N + nn]; // pull neighbor for distribution 9
if (f10 > 0) {
@ -171,8 +192,10 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n + Nx * Ny + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary
if (!(k+1<Nz)) nn -= Nx*Ny*Nz; // Perioidic BC along the z-boundary
if (!(i + 1 < Nx))
nn -= Nx; // periodic BC along the x-boundary
if (!(k + 1 < Nz))
nn -= Nx * Ny * Nz; // Perioidic BC along the z-boundary
//if ( !(i-1<0) && !(k-1<0)){
f12 = disteven[6 * N + nn]; // pull distribution 11
if (f12 > 0) {
@ -182,8 +205,10 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n - Nx * Ny + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary
if (k-1<0) nn += Nx*Ny*Nz; // Perioidic BC along the z-boundary
if (!(i + 1 < Nx))
nn -= Nx; // periodic BC along the x-boundary
if (k - 1 < 0)
nn += Nx * Ny * Nz; // Perioidic BC along the z-boundary
//if (!(i-1<0) && (k+1<Nz)){
f14 = disteven[7 * N + nn]; // pull neighbor for distribution 13
if (f14 > 0) {
@ -193,8 +218,10 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n + Nx * Ny + Nx; // neighbor index (pull convention)
if (!(j+1<Ny)) nn -= Nx*Ny; // Perioidic BC along the y-boundary
if (!(k+1<Nz)) nn -= Nx*Ny*Nz; // Perioidic BC along the z-boundary
if (!(j + 1 < Ny))
nn -= Nx * Ny; // Perioidic BC along the y-boundary
if (!(k + 1 < Nz))
nn -= Nx * Ny * Nz; // Perioidic BC along the z-boundary
//if (!(j-1<0) && !(k-1<0)){
f16 = disteven[8 * N + nn]; // pull neighbor for distribution 15
if (f16 > 0) {
@ -204,8 +231,10 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
}
//........................................................................
nn = n - Nx * Ny + Nx; // neighbor index (pull convention)
if (!(j+1<Ny)) nn -= Nx*Ny; // Perioidic BC along the y-boundary
if (k-1<0) nn += Nx*Ny*Nz; // Perioidic BC along the z-boundary
if (!(j + 1 < Ny))
nn -= Nx * Ny; // Perioidic BC along the y-boundary
if (k - 1 < 0)
nn += Nx * Ny * Nz; // Perioidic BC along the z-boundary
//if (!(j-1<0) && (k+1<Nz)){
f18 = disteven[9 * N + nn]; // pull neighbor for distribution 17
if (f18 > 0) {
@ -214,13 +243,12 @@ extern "C" void ScaLBL_D3Q19_Swap(char *ID, double *disteven, double *distodd, i
// }
}
//........................................................................
}
}
}
extern "C" void ScaLBL_D3Q19_Swap_Compact(int *neighborList, double *disteven, double *distodd, int Np)
{
extern "C" void ScaLBL_D3Q19_Swap_Compact(int *neighborList, double *disteven,
double *distodd, int Np) {
int q, n, nn;
double f1, f2;
for (q = 0; q < 9; q++) {
@ -236,9 +264,8 @@ extern "C" void ScaLBL_D3Q19_Swap_Compact(int *neighborList, double *disteven, d
}
}
extern "C" double ScaLBL_D3Q19_Flux_BC_z(double *disteven, double *distodd, double flux,
int Nx, int Ny, int Nz){
extern "C" double ScaLBL_D3Q19_Flux_BC_z(double *disteven, double *distodd,
double flux, int Nx, int Ny, int Nz) {
// Note that this routine assumes the distributions are stored "opposite"
// odd distributions in disteven and even distributions in distodd.
int n, N;
@ -279,15 +306,16 @@ extern "C" double ScaLBL_D3Q19_Flux_BC_z(double *disteven, double *distodd, doub
// Determine the outlet flow velocity
//sum += 1.0 - (f0+f4+f3+f2+f1+f8+f7+f9+ f10 + 2*(f5+ f15+f18+f11+f14))/din;
//sum += (f0+f4+f3+f2+f1+f8+f7+f9+ f10 + 2*(f5+f15+f18+f11+f14));
sum += (f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f6+f12+f13+f16+f17));
sum += (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f6 + f12 + f13 + f16 + f17));
}
din = sum / (A * (1.0 - flux));
return din;
}
extern "C" double ScaLBL_D3Q19_AAodd_Flux_BC_z(int *d_neighborList, int *list, double *dist, double flux,
double area, int count, int Np)
{
extern "C" double ScaLBL_D3Q19_AAodd_Flux_BC_z(int *d_neighborList, int *list,
double *dist, double flux,
double area, int count, int Np) {
int idx, n;
int nread;
@ -339,15 +367,16 @@ extern "C" double ScaLBL_D3Q19_AAodd_Flux_BC_z(int *d_neighborList, int *list, d
nread = d_neighborList[n + 15 * Np];
double f16 = dist[nread];
sum += factor*(f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f6+f12+f13+f16+f17));
sum += factor * (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f6 + f12 + f13 + f16 + f17));
}
return sum;
}
extern "C" double ScaLBL_D3Q19_AAeven_Flux_BC_z(int *list, double *dist, double flux, double area,
int count, int Np)
{
extern "C" double ScaLBL_D3Q19_AAeven_Flux_BC_z(int *list, double *dist,
double flux, double area,
int count, int Np) {
int idx, n;
// distributions
double factor = 1.f / (area);
@ -369,14 +398,15 @@ extern "C" double ScaLBL_D3Q19_AAeven_Flux_BC_z(int *list, double *dist, double
double f13 = dist[14 * Np + n];
double f16 = dist[15 * Np + n];
double f17 = dist[18 * Np + n];
sum += factor*(f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f6+f12+f13+f16+f17));
sum += factor * (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f6 + f12 + f13 + f16 + f17));
}
return sum;
}
extern "C" double ScaLBL_D3Q19_Flux_BC_Z(double *disteven, double *distodd, double flux,
int Nx, int Ny, int Nz, int outlet){
extern "C" double ScaLBL_D3Q19_Flux_BC_Z(double *disteven, double *distodd,
double flux, int Nx, int Ny, int Nz,
int outlet) {
// Note that this routine assumes the distributions are stored "opposite"
// odd distributions in disteven and even distributions in distodd.
int n, N;
@ -414,14 +444,15 @@ extern "C" double ScaLBL_D3Q19_Flux_BC_Z(double *disteven, double *distodd, doub
//double f16 = disteven[8*N+n];
double f18 = disteven[9 * N + n];
sum += (f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f5+f11+f14+f15+f18));
sum += (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f5 + f11 + f14 + f15 + f18));
}
dout = sum / (A * (1.0 + flux));
return dout;
}
extern "C" void ScaLBL_D3Q19_Reflection_BC_z(int *list, double *dist, int count, int Np){
extern "C" void ScaLBL_D3Q19_Reflection_BC_z(int *list, double *dist, int count,
int Np) {
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
@ -439,7 +470,8 @@ extern "C" void ScaLBL_D3Q19_Reflection_BC_z(int *list, double *dist, int count,
}
}
extern "C" void ScaLBL_D3Q19_Reflection_BC_Z(int *list, double *dist, int count, int Np){
extern "C" void ScaLBL_D3Q19_Reflection_BC_Z(int *list, double *dist, int count,
int Np) {
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
@ -457,8 +489,9 @@ extern "C" void ScaLBL_D3Q19_Reflection_BC_Z(int *list, double *dist, int count,
}
}
extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_z(int *list, double *dist, double din, int count, int Np)
{
extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_z(int *list, double *dist,
double din, int count,
int Np) {
// distributions
double ux, uy, uz, Cyz, Cxz;
ux = uy = 0.0;
@ -482,7 +515,8 @@ extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_z(int *list, double *dist, doubl
// Determine the inlet flow velocity
//ux = (f1-f2+f7-f8+f9-f10+f11-f12+f13-f14);
//uy = (f3-f4+f7-f8-f9+f10+f15-f16+f17-f18);
uz = din - (f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f6+f12+f13+f16+f17));
uz = din - (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f6 + f12 + f13 + f16 + f17));
Cxz = 0.5 * (f1 + f7 + f9 - f2 - f10 - f8) - 0.3333333333333333 * ux;
Cyz = 0.5 * (f3 + f7 + f10 - f4 - f9 - f8) - 0.3333333333333333 * uy;
@ -501,8 +535,9 @@ extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_z(int *list, double *dist, doubl
}
}
extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_Z(int *list, double *dist, double dout, int count, int Np)
{
extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_Z(int *list, double *dist,
double dout, int count,
int Np) {
// distributions
double ux, uy, uz, Cyz, Cxz;
ux = uy = 0.0;
@ -529,7 +564,8 @@ extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_Z(int *list, double *dist, doubl
// Determine the outlet flow velocity
//ux = f1-f2+f7-f8+f9-f10+f11-f12+f13-f14;
//uy = f3-f4+f7-f8-f9+f10+f15-f16+f17-f18;
uz = -dout + (f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f5+f11+f14+f15+f18));
uz = -dout + (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f5 + f11 + f14 + f15 + f18));
Cxz = 0.5 * (f1 + f7 + f9 - f2 - f10 - f8) - 0.3333333333333333 * ux;
Cyz = 0.5 * (f3 + f7 + f10 - f4 - f9 - f8) - 0.3333333333333333 * uy;
@ -549,8 +585,9 @@ extern "C" void ScaLBL_D3Q19_AAeven_Pressure_BC_Z(int *list, double *dist, doubl
}
}
extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_z(int *d_neighborList, int *list, double *dist, double din, int count, int Np)
{
extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_z(int *d_neighborList, int *list,
double *dist, double din,
int count, int Np) {
int nread;
int nr5, nr11, nr14, nr15, nr18;
// distributions
@ -611,7 +648,8 @@ extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_z(int *d_neighborList, int *list,
// Determine the inlet flow velocity
//ux = (f1-f2+f7-f8+f9-f10+f11-f12+f13-f14);
//uy = (f3-f4+f7-f8-f9+f10+f15-f16+f17-f18);
uz = din - (f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f6+f12+f13+f16+f17));
uz = din - (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f6 + f12 + f13 + f16 + f17));
Cxz = 0.5 * (f1 + f7 + f9 - f2 - f10 - f8) - 0.3333333333333333 * ux;
Cyz = 0.5 * (f3 + f7 + f10 - f4 - f9 - f8) - 0.3333333333333333 * uy;
@ -630,8 +668,9 @@ extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_z(int *d_neighborList, int *list,
}
}
extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_Z(int *d_neighborList, int *list, double *dist, double dout, int count, int Np)
{
extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_Z(int *d_neighborList, int *list,
double *dist, double dout,
int count, int Np) {
int nread;
int nr6, nr12, nr13, nr16, nr17;
// distributions
@ -666,7 +705,6 @@ extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_Z(int *d_neighborList, int *list,
nread = d_neighborList[n + 14 * Np];
double f15 = dist[nread];
nread = d_neighborList[n + Np];
double f2 = dist[nread];
@ -695,7 +733,8 @@ extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_Z(int *d_neighborList, int *list,
// Determine the inlet flow velocity
//ux = f1-f2+f7-f8+f9-f10+f11-f12+f13-f14;
//uy = f3-f4+f7-f8-f9+f10+f15-f16+f17-f18;
uz = -dout + (f0+f1+f2+f3+f4+f7+f8+f9+f10 + 2*(f5+f11+f14+f15+f18));
uz = -dout + (f0 + f1 + f2 + f3 + f4 + f7 + f8 + f9 + f10 +
2 * (f5 + f11 + f14 + f15 + f18));
Cxz = 0.5 * (f1 + f7 + f9 - f2 - f10 - f8) - 0.3333333333333333 * ux;
Cyz = 0.5 * (f3 + f7 + f10 - f4 - f9 - f8) - 0.3333333333333333 * uy;
@ -716,9 +755,8 @@ extern "C" void ScaLBL_D3Q19_AAodd_Pressure_BC_Z(int *d_neighborList, int *list,
}
}
extern "C" void ScaLBL_D3Q19_Velocity_BC_z(double *disteven, double *distodd, double uz,
int Nx, int Ny, int Nz)
{
extern "C" void ScaLBL_D3Q19_Velocity_BC_z(double *disteven, double *distodd,
double uz, int Nx, int Ny, int Nz) {
int n, N;
// distributions
double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9;
@ -758,12 +796,16 @@ extern "C" void ScaLBL_D3Q19_Velocity_BC_z(double *disteven, double *distodd, do
// Determine the outlet flow velocity
// uz = 1.0 - (f0+f4+f3+f2+f1+f8+f7+f9+f10 +
// 2*(f5+f15+f18+f11+f14))/din;
din = (f0+f4+f3+f2+f1+f8+f7+f9+f10+2*(f5+f15+f18+f11+f14))/(1.0-uz);
din = (f0 + f4 + f3 + f2 + f1 + f8 + f7 + f9 + f10 +
2 * (f5 + f15 + f18 + f11 + f14)) /
(1.0 - uz);
// Set the unknown distributions:
f6 = f5 + 0.3333333333333333 * din * uz;
f16 = f15 + 0.1666666666666667 * din * uz;
f17 = f16 + f4 - f3 - f15 + f18 + f8 - f7 + f9 - f10;
f12= (din*uz+f5+ f15+f18+f11+f14-f6-f16-f17-f2+f1-f14+f11-f8+f7+f9-f10)*0.5;
f12 = (din * uz + f5 + f15 + f18 + f11 + f14 - f6 - f16 - f17 - f2 +
f1 - f14 + f11 - f8 + f7 + f9 - f10) *
0.5;
f13 = din * uz + f5 + f15 + f18 + f11 + f14 - f6 - f16 - f17 - f12;
//........Store in "opposite" memory location..........
@ -776,9 +818,9 @@ extern "C" void ScaLBL_D3Q19_Velocity_BC_z(double *disteven, double *distodd, do
}
}
extern "C" void ScaLBL_D3Q19_Velocity_BC_Z(double *disteven, double *distodd, double uz,
int Nx, int Ny, int Nz, int outlet)
{
extern "C" void ScaLBL_D3Q19_Velocity_BC_Z(double *disteven, double *distodd,
double uz, int Nx, int Ny, int Nz,
int outlet) {
int n, N;
// distributions
double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9;
@ -813,11 +855,15 @@ extern "C" void ScaLBL_D3Q19_Velocity_BC_Z(double *disteven, double *distodd, do
f16 = disteven[8 * N + n];
f18 = disteven[9 * N + n];
//uz = -1.0 + (f0+f4+f3+f2+f1+f8+f7+f9+f10 + 2*(f6+f16+f17+f12+f13))/dout;
dout = (f0+f4+f3+f2+f1+f8+f7+f9+f10 + 2*(f6+f16+f17+f12+f13))/(1.0+uz);
dout = (f0 + f4 + f3 + f2 + f1 + f8 + f7 + f9 + f10 +
2 * (f6 + f16 + f17 + f12 + f13)) /
(1.0 + uz);
f5 = f6 - 0.33333333333333338 * dout * uz;
f15 = f16 - 0.16666666666666678 * dout * uz;
f18 = f15 - f4 + f3 - f16 + f17 - f8 + f7 - f9 + f10;
f11 = (-dout*uz+f6+ f16+f17+f12+f13-f5-f15-f18+f2-f1-f13+f12+f8-f7-f9+f10)*0.5;
f11 = (-dout * uz + f6 + f16 + f17 + f12 + f13 - f5 - f15 - f18 + f2 -
f1 - f13 + f12 + f8 - f7 - f9 + f10) *
0.5;
f14 = -dout * uz + f6 + f16 + f17 + f12 + f13 - f5 - f15 - f18 - f11;
//........Store in "opposite" memory location..........
distodd[2 * N + n] = f5;
@ -829,8 +875,7 @@ extern "C" void ScaLBL_D3Q19_Velocity_BC_Z(double *disteven, double *distodd, do
}
}
extern "C" void ScaLBL_D3Q19_Momentum(double *dist, double *vel, int Np)
{
extern "C" void ScaLBL_D3Q19_Momentum(double *dist, double *vel, int Np) {
int n;
int N = Np;
// distributions
@ -873,8 +918,7 @@ extern "C" void ScaLBL_D3Q19_Momentum(double *dist, double *vel, int Np)
}
}
extern "C" void ScaLBL_D3Q19_Pressure(double *dist, double *Pressure, int N)
{
extern "C" void ScaLBL_D3Q19_Pressure(double *dist, double *Pressure, int N) {
for (int n = 0; n < N; n++) {
//........................................................................
// Registers to store the distributions
@ -900,14 +944,16 @@ extern "C" void ScaLBL_D3Q19_Pressure(double *dist, double *Pressure, int N)
double f15 = dist[15 * N + n];
double f17 = dist[17 * N + n];
//.................Compute the velocity...................................
Pressure[n] = 0.3333333333333333*(f0+f2+f1+f4+f3+f6+f5+f8+f7+f10+
f9+f12+f11+f14+f13+f16+f15+f18+f17);
Pressure[n] = 0.3333333333333333 *
(f0 + f2 + f1 + f4 + f3 + f6 + f5 + f8 + f7 + f10 + f9 +
f12 + f11 + f14 + f13 + f16 + f15 + f18 + f17);
}
}
extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish, int Np, double rlx_setA, double rlx_setB, double Fx,
double Fy, double Fz)
{
extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish,
int Np, double rlx_setA,
double rlx_setB, double Fx, double Fy,
double Fz) {
// conserved momemnts
double rho, jx, jy, jz;
// non-conserved moments
@ -1197,8 +1243,6 @@ extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish, int
m17 -= fq;
m18 -= fq;
//........................................................................
// READ THE DISTRIBUTIONS
// (read from opposite array due to previous swap operation)
@ -1206,13 +1250,19 @@ extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish, int
//..............incorporate external force................................................
//..............carry out relaxation process...............................................
m1 = m1 + rlx_setA*((19*(jx*jx+jy*jy+jz*jz)/rho - 11*rho) - m1);
m2 = m2 + rlx_setA*((3*rho - 5.5*(jx*jx+jy*jy+jz*jz)/rho) - m2);
m1 = m1 +
rlx_setA *
((19 * (jx * jx + jy * jy + jz * jz) / rho - 11 * rho) - m1);
m2 = m2 +
rlx_setA *
((3 * rho - 5.5 * (jx * jx + jy * jy + jz * jz) / rho) - m2);
m4 = m4 + rlx_setB * ((-0.6666666666666666 * jx) - m4);
m6 = m6 + rlx_setB * ((-0.6666666666666666 * jy) - m6);
m8 = m8 + rlx_setB * ((-0.6666666666666666 * jz) - m8);
m9 = m9 + rlx_setA * (((2 * jx * jx - jy * jy - jz * jz) / rho) - m9);
m10 = m10 + rlx_setA*(-0.5*((2*jx*jx-jy*jy-jz*jz)/rho) - m10);
m10 =
m10 +
rlx_setA * (-0.5 * ((2 * jx * jx - jy * jy - jz * jz) / rho) - m10);
m11 = m11 + rlx_setA * (((jy * jy - jz * jz) / rho) - m11);
m12 = m12 + rlx_setA * (-0.5 * ((jy * jy - jz * jz) / rho) - m12);
m13 = m13 + rlx_setA * ((jx * jy / rho) - m13);
@ -1229,114 +1279,124 @@ extern "C" void ScaLBL_D3Q19_AAeven_MRT(double *dist, int start, int finish, int
dist[n] = fq;
// q = 1
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(jx-m4)+mrt_V6*(m9-m10) + 0.16666666*Fx;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (jx - m4) +
mrt_V6 * (m9 - m10) + 0.16666666 * Fx;
dist[1 * Np + n] = fq;
// q=2
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(m4-jx)+mrt_V6*(m9-m10) - 0.16666666*Fx;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (m4 - jx) +
mrt_V6 * (m9 - m10) - 0.16666666 * Fx;
dist[2 * Np + n] = fq;
// q = 3
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(jy-m6)+mrt_V7*(m10-m9)+mrt_V8*(m11-m12) + 0.16666666*Fy;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (jy - m6) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m11 - m12) + 0.16666666 * Fy;
dist[3 * Np + n] = fq;
// q = 4
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(m6-jy)+mrt_V7*(m10-m9)+mrt_V8*(m11-m12) - 0.16666666*Fy;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (m6 - jy) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m11 - m12) - 0.16666666 * Fy;
dist[4 * Np + n] = fq;
// q = 5
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(jz-m8)+mrt_V7*(m10-m9)+mrt_V8*(m12-m11) + 0.16666666*Fz;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (jz - m8) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m12 - m11) + 0.16666666 * Fz;
dist[5 * Np + n] = fq;
// q = 6
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(m8-jz)+mrt_V7*(m10-m9)+mrt_V8*(m12-m11) - 0.16666666*Fz;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (m8 - jz) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m12 - m11) - 0.16666666 * Fz;
dist[6 * Np + n] = fq;
// q = 7
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2+0.1*(jx+jy)+0.025*(m4+m6)
+mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12+0.25*m13+0.125*(m16-m17) + 0.08333333333*(Fx+Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx + jy) +
0.025 * (m4 + m6) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 + 0.25 * m13 + 0.125 * (m16 - m17) +
0.08333333333 * (Fx + Fy);
dist[7 * Np + n] = fq;
// q = 8
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2-0.1*(jx+jy)-0.025*(m4+m6) +mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12+0.25*m13+0.125*(m17-m16) - 0.08333333333*(Fx+Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 - 0.1 * (jx + jy) -
0.025 * (m4 + m6) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 + 0.25 * m13 + 0.125 * (m17 - m16) -
0.08333333333 * (Fx + Fy);
dist[8 * Np + n] = fq;
// q = 9
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2+0.1*(jx-jy)+0.025*(m4-m6)
+mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12-0.25*m13+0.125*(m16+m17) + 0.08333333333*(Fx-Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx - jy) +
0.025 * (m4 - m6) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 - 0.25 * m13 + 0.125 * (m16 + m17) +
0.08333333333 * (Fx - Fy);
dist[9 * Np + n] = fq;
// q = 10
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2+0.1*(jy-jx)+0.025*(m6-m4)
+mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12-0.25*m13-0.125*(m16+m17)- 0.08333333333*(Fx-Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jy - jx) +
0.025 * (m6 - m4) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 - 0.25 * m13 - 0.125 * (m16 + m17) -
0.08333333333 * (Fx - Fy);
dist[10 * Np + n] = fq;
// q = 11
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jx+jz)+0.025*(m4+m8)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12+0.25*m15+0.125*(m18-m16) + 0.08333333333*(Fx+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx + jz) +
0.025 * (m4 + m8) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 + 0.25 * m15 + 0.125 * (m18 - m16) +
0.08333333333 * (Fx + Fz);
dist[11 * Np + n] = fq;
// q = 12
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2-0.1*(jx+jz)-0.025*(m4+m8)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12+0.25*m15+0.125*(m16-m18) - 0.08333333333*(Fx+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 - 0.1 * (jx + jz) -
0.025 * (m4 + m8) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 + 0.25 * m15 + 0.125 * (m16 - m18) -
0.08333333333 * (Fx + Fz);
dist[12 * Np + n] = fq;
// q = 13
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jx-jz)+0.025*(m4-m8)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12-0.25*m15-0.125*(m16+m18) + 0.08333333333*(Fx-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx - jz) +
0.025 * (m4 - m8) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 - 0.25 * m15 - 0.125 * (m16 + m18) +
0.08333333333 * (Fx - Fz);
dist[13 * Np + n] = fq;
// q= 14
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jz-jx)+0.025*(m8-m4)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12-0.25*m15+0.125*(m16+m18) - 0.08333333333*(Fx-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jz - jx) +
0.025 * (m8 - m4) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 - 0.25 * m15 + 0.125 * (m16 + m18) -
0.08333333333 * (Fx - Fz);
dist[14 * Np + n] = fq;
// q = 15
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jy+jz)+0.025*(m6+m8)
-mrt_V6*m9-mrt_V7*m10+0.25*m14+0.125*(m17-m18) + 0.08333333333*(Fy+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jy + jz) +
0.025 * (m6 + m8) - mrt_V6 * m9 - mrt_V7 * m10 + 0.25 * m14 +
0.125 * (m17 - m18) + 0.08333333333 * (Fy + Fz);
dist[15 * Np + n] = fq;
// q = 16
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2-0.1*(jy+jz)-0.025*(m6+m8)
-mrt_V6*m9-mrt_V7*m10+0.25*m14+0.125*(m18-m17)- 0.08333333333*(Fy+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 - 0.1 * (jy + jz) -
0.025 * (m6 + m8) - mrt_V6 * m9 - mrt_V7 * m10 + 0.25 * m14 +
0.125 * (m18 - m17) - 0.08333333333 * (Fy + Fz);
dist[16 * Np + n] = fq;
// q = 17
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jy-jz)+0.025*(m6-m8)
-mrt_V6*m9-mrt_V7*m10-0.25*m14+0.125*(m17+m18) + 0.08333333333*(Fy-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jy - jz) +
0.025 * (m6 - m8) - mrt_V6 * m9 - mrt_V7 * m10 - 0.25 * m14 +
0.125 * (m17 + m18) + 0.08333333333 * (Fy - Fz);
dist[17 * Np + n] = fq;
// q = 18
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jz-jy)+0.025*(m8-m6)
-mrt_V6*m9-mrt_V7*m10-0.25*m14-0.125*(m17+m18) - 0.08333333333*(Fy-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jz - jy) +
0.025 * (m8 - m6) - mrt_V6 * m9 - mrt_V7 * m10 - 0.25 * m14 -
0.125 * (m17 + m18) - 0.08333333333 * (Fy - Fz);
dist[18 * Np + n] = fq;
//........................................................................
}
}
extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int start, int finish, int Np, double rlx_setA, double rlx_setB, double Fx,
double Fy, double Fz)
{
extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist,
int start, int finish, int Np,
double rlx_setA, double rlx_setB,
double Fx, double Fy, double Fz) {
// conserved momemnts
double rho, jx, jy, jz;
// non-conserved moments
@ -1354,7 +1414,6 @@ extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int star
constexpr double mrt_V11 = 0.01388888888888889;
constexpr double mrt_V12 = 0.04166666666666666;
int nread;
for (int n = start; n < finish; n++) {
// q=0
@ -1376,7 +1435,8 @@ extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int star
m10 = -4.0 * fq;
// f2 = dist[10*Np+n];
nread = neighborList[n+Np]; // neighbor 1 ( < 10Np => even part of dist)
nread =
neighborList[n + Np]; // neighbor 1 ( < 10Np => even part of dist)
fq = dist[nread]; // reading the f2 data into register fq
//fq = dist[Np+n];
rho += fq;
@ -1429,7 +1489,6 @@ extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int star
m11 -= fq;
m12 += 2.0 * fq;
// q = 6
nread = neighborList[n + 5 * Np];
fq = dist[nread];
@ -1666,13 +1725,19 @@ extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int star
//..............incorporate external force................................................
//..............carry out relaxation process...............................................
m1 = m1 + rlx_setA*((19*(jx*jx+jy*jy+jz*jz)/rho - 11*rho) - m1);
m2 = m2 + rlx_setA*((3*rho - 5.5*(jx*jx+jy*jy+jz*jz)/rho) - m2);
m1 = m1 +
rlx_setA *
((19 * (jx * jx + jy * jy + jz * jz) / rho - 11 * rho) - m1);
m2 = m2 +
rlx_setA *
((3 * rho - 5.5 * (jx * jx + jy * jy + jz * jz) / rho) - m2);
m4 = m4 + rlx_setB * ((-0.6666666666666666 * jx) - m4);
m6 = m6 + rlx_setB * ((-0.6666666666666666 * jy) - m6);
m8 = m8 + rlx_setB * ((-0.6666666666666666 * jz) - m8);
m9 = m9 + rlx_setA * (((2 * jx * jx - jy * jy - jz * jz) / rho) - m9);
m10 = m10 + rlx_setA*(-0.5*((2*jx*jx-jy*jy-jz*jz)/rho) - m10);
m10 =
m10 +
rlx_setA * (-0.5 * ((2 * jx * jx - jy * jy - jz * jz) / rho) - m10);
m11 = m11 + rlx_setA * (((jy * jy - jz * jz) / rho) - m11);
m12 = m12 + rlx_setA * (-0.5 * ((jy * jy - jz * jz) / rho) - m12);
m13 = m13 + rlx_setA * ((jx * jy / rho) - m13);
@ -1689,128 +1754,136 @@ extern "C" void ScaLBL_D3Q19_AAodd_MRT(int *neighborList, double *dist, int star
dist[n] = fq;
// q = 1
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(jx-m4)+mrt_V6*(m9-m10)+0.16666666*Fx;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (jx - m4) +
mrt_V6 * (m9 - m10) + 0.16666666 * Fx;
nread = neighborList[n + Np];
dist[nread] = fq;
// q=2
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(m4-jx)+mrt_V6*(m9-m10) - 0.16666666*Fx;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (m4 - jx) +
mrt_V6 * (m9 - m10) - 0.16666666 * Fx;
nread = neighborList[n];
dist[nread] = fq;
// q = 3
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(jy-m6)+mrt_V7*(m10-m9)+mrt_V8*(m11-m12) + 0.16666666*Fy;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (jy - m6) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m11 - m12) + 0.16666666 * Fy;
nread = neighborList[n + 3 * Np];
dist[nread] = fq;
// q = 4
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(m6-jy)+mrt_V7*(m10-m9)+mrt_V8*(m11-m12) - 0.16666666*Fy;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (m6 - jy) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m11 - m12) - 0.16666666 * Fy;
nread = neighborList[n + 2 * Np];
dist[nread] = fq;
// q = 5
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(jz-m8)+mrt_V7*(m10-m9)+mrt_V8*(m12-m11) + 0.16666666*Fz;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (jz - m8) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m12 - m11) + 0.16666666 * Fz;
nread = neighborList[n + 5 * Np];
dist[nread] = fq;
// q = 6
fq = mrt_V1*rho-mrt_V4*m1-mrt_V5*m2+0.1*(m8-jz)+mrt_V7*(m10-m9)+mrt_V8*(m12-m11) - 0.16666666*Fz;
fq = mrt_V1 * rho - mrt_V4 * m1 - mrt_V5 * m2 + 0.1 * (m8 - jz) +
mrt_V7 * (m10 - m9) + mrt_V8 * (m12 - m11) - 0.16666666 * Fz;
nread = neighborList[n + 4 * Np];
dist[nread] = fq;
// q = 7
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2+0.1*(jx+jy)+0.025*(m4+m6)
+mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12+0.25*m13+0.125*(m16-m17) + 0.08333333333*(Fx+Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx + jy) +
0.025 * (m4 + m6) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 + 0.25 * m13 + 0.125 * (m16 - m17) +
0.08333333333 * (Fx + Fy);
nread = neighborList[n + 7 * Np];
dist[nread] = fq;
// q = 8
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2-0.1*(jx+jy)-0.025*(m4+m6) +mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12+0.25*m13+0.125*(m17-m16) - 0.08333333333*(Fx+Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 - 0.1 * (jx + jy) -
0.025 * (m4 + m6) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 + 0.25 * m13 + 0.125 * (m17 - m16) -
0.08333333333 * (Fx + Fy);
nread = neighborList[n + 6 * Np];
dist[nread] = fq;
// q = 9
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2+0.1*(jx-jy)+0.025*(m4-m6)
+mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12-0.25*m13+0.125*(m16+m17) + 0.08333333333*(Fx-Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx - jy) +
0.025 * (m4 - m6) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 - 0.25 * m13 + 0.125 * (m16 + m17) +
0.08333333333 * (Fx - Fy);
nread = neighborList[n + 9 * Np];
dist[nread] = fq;
// q = 10
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2+0.1*(jy-jx)+0.025*(m6-m4)
+mrt_V7*m9+mrt_V11*m10+mrt_V8*m11
+mrt_V12*m12-0.25*m13-0.125*(m16+m17)- 0.08333333333*(Fx-Fy);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jy - jx) +
0.025 * (m6 - m4) + mrt_V7 * m9 + mrt_V11 * m10 + mrt_V8 * m11 +
mrt_V12 * m12 - 0.25 * m13 - 0.125 * (m16 + m17) -
0.08333333333 * (Fx - Fy);
nread = neighborList[n + 8 * Np];
dist[nread] = fq;
// q = 11
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jx+jz)+0.025*(m4+m8)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12+0.25*m15+0.125*(m18-m16) + 0.08333333333*(Fx+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx + jz) +
0.025 * (m4 + m8) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 + 0.25 * m15 + 0.125 * (m18 - m16) +
0.08333333333 * (Fx + Fz);
nread = neighborList[n + 11 * Np];
dist[nread] = fq;
// q = 12
fq = mrt_V1*rho+mrt_V9*m1+mrt_V10*m2-0.1*(jx+jz)-0.025*(m4+m8)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12+0.25*m15+0.125*(m16-m18) - 0.08333333333*(Fx+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 - 0.1 * (jx + jz) -
0.025 * (m4 + m8) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 + 0.25 * m15 + 0.125 * (m16 - m18) -
0.08333333333 * (Fx + Fz);
nread = neighborList[n + 10 * Np];
dist[nread] = fq;
// q = 13
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jx-jz)+0.025*(m4-m8)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12-0.25*m15-0.125*(m16+m18) + 0.08333333333*(Fx-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jx - jz) +
0.025 * (m4 - m8) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 - 0.25 * m15 - 0.125 * (m16 + m18) +
0.08333333333 * (Fx - Fz);
nread = neighborList[n + 13 * Np];
dist[nread] = fq;
// q= 14
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jz-jx)+0.025*(m8-m4)
+mrt_V7*m9+mrt_V11*m10-mrt_V8*m11
-mrt_V12*m12-0.25*m15+0.125*(m16+m18) - 0.08333333333*(Fx-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jz - jx) +
0.025 * (m8 - m4) + mrt_V7 * m9 + mrt_V11 * m10 - mrt_V8 * m11 -
mrt_V12 * m12 - 0.25 * m15 + 0.125 * (m16 + m18) -
0.08333333333 * (Fx - Fz);
nread = neighborList[n + 12 * Np];
dist[nread] = fq;
// q = 15
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jy+jz)+0.025*(m6+m8)
-mrt_V6*m9-mrt_V7*m10+0.25*m14+0.125*(m17-m18) + 0.08333333333*(Fy+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jy + jz) +
0.025 * (m6 + m8) - mrt_V6 * m9 - mrt_V7 * m10 + 0.25 * m14 +
0.125 * (m17 - m18) + 0.08333333333 * (Fy + Fz);
nread = neighborList[n + 15 * Np];
dist[nread] = fq;
// q = 16
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2-0.1*(jy+jz)-0.025*(m6+m8)
-mrt_V6*m9-mrt_V7*m10+0.25*m14+0.125*(m18-m17)- 0.08333333333*(Fy+Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 - 0.1 * (jy + jz) -
0.025 * (m6 + m8) - mrt_V6 * m9 - mrt_V7 * m10 + 0.25 * m14 +
0.125 * (m18 - m17) - 0.08333333333 * (Fy + Fz);
nread = neighborList[n + 14 * Np];
dist[nread] = fq;
// q = 17
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jy-jz)+0.025*(m6-m8)
-mrt_V6*m9-mrt_V7*m10-0.25*m14+0.125*(m17+m18) + 0.08333333333*(Fy-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jy - jz) +
0.025 * (m6 - m8) - mrt_V6 * m9 - mrt_V7 * m10 - 0.25 * m14 +
0.125 * (m17 + m18) + 0.08333333333 * (Fy - Fz);
nread = neighborList[n + 17 * Np];
dist[nread] = fq;
// q = 18
fq = mrt_V1*rho+mrt_V9*m1
+mrt_V10*m2+0.1*(jz-jy)+0.025*(m8-m6)
-mrt_V6*m9-mrt_V7*m10-0.25*m14-0.125*(m17+m18) - 0.08333333333*(Fy-Fz);
fq = mrt_V1 * rho + mrt_V9 * m1 + mrt_V10 * m2 + 0.1 * (jz - jy) +
0.025 * (m8 - m6) - mrt_V6 * m9 - mrt_V7 * m10 - 0.25 * m14 -
0.125 * (m17 + m18) - 0.08333333333 * (Fy - Fz);
nread = neighborList[n + 16 * Np];
dist[nread] = fq;
}
}
extern "C" void ScaLBL_D3Q19_AAeven_Compact(char * ID, double *dist, int Np)
{
extern "C" void ScaLBL_D3Q19_AAeven_Compact(char *ID, double *dist, int Np) {
for (int n = 0; n < Np; n++) {
@ -1868,8 +1941,8 @@ extern "C" void ScaLBL_D3Q19_AAeven_Compact(char * ID, double *dist, int Np)
}
}
extern "C" void ScaLBL_D3Q19_AAodd_Compact(char * ID, int *neighborList, double *dist, int Np)
{
extern "C" void ScaLBL_D3Q19_AAodd_Compact(char *ID, int *neighborList,
double *dist, int Np) {
int nread;
for (int n = 0; n < Np; n++) {
@ -1904,7 +1977,6 @@ extern "C" void ScaLBL_D3Q19_AAodd_Compact(char * ID, int *neighborList, double
nread = neighborList[n + 16 * Np];
double f18 = dist[nread];
nread = neighborList[n + Np];
double f1 = dist[nread];
@ -1932,7 +2004,6 @@ extern "C" void ScaLBL_D3Q19_AAodd_Compact(char * ID, int *neighborList, double
nread = neighborList[n + 17 * Np];
double f17 = dist[nread];
nread = neighborList[n];
dist[nread] = f1;
@ -1960,7 +2031,6 @@ extern "C" void ScaLBL_D3Q19_AAodd_Compact(char * ID, int *neighborList, double
nread = neighborList[n + 16 * Np];
dist[nread] = f17;
nread = neighborList[n + Np];
dist[nread] = f2;

View File

@ -1,6 +1,23 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
Copyright Equnior ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// CPU Functions for D3Q7 Lattice Boltzmann Methods
extern "C" void ScaLBL_Scalar_Pack(int *list, int count, double *sendbuf, double *Data, int N){
extern "C" void ScaLBL_Scalar_Pack(int *list, int count, double *sendbuf,
double *Data, int N) {
//....................................................................................
// Pack distribution q into the send buffer for the listed lattice sites
// dist may be even or odd distributions stored by stream layout
@ -11,7 +28,8 @@ extern "C" void ScaLBL_Scalar_Pack(int *list, int count, double *sendbuf, double
sendbuf[idx] = Data[n];
}
}
extern "C" void ScaLBL_Scalar_Unpack(int *list, int count, double *recvbuf, double *Data, int N){
extern "C" void ScaLBL_Scalar_Unpack(int *list, int count, double *recvbuf,
double *Data, int N) {
//....................................................................................
// Pack distribution q into the send buffer for the listed lattice sites
// dist may be even or odd distributions stored by stream layout
@ -36,14 +54,14 @@ extern "C" void ScaLBL_D3Q7_Unpack(int q, int *list, int start, int count,
// Get the value from the list -- note that n is the index is from the send (non-local) process
n = list[idx];
// unpack the distribution to the proper location
if (!(n<0)) dist[q*N+n] = recvbuf[start+idx];
if (!(n < 0))
dist[q * N + n] = recvbuf[start + idx];
//dist[q*N+n] = recvbuf[start+idx];
}
}
extern "C" void ScaLBL_PackDenD3Q7(int *list, int count, double *sendbuf, int number, double *Data, int N){
extern "C" void ScaLBL_PackDenD3Q7(int *list, int count, double *sendbuf,
int number, double *Data, int N) {
//....................................................................................
// Pack distribution into the send buffer for the listed lattice sites
//....................................................................................
@ -52,13 +70,14 @@ extern "C" void ScaLBL_PackDenD3Q7(int *list, int count, double *sendbuf, int nu
for (component = 0; component < number; component++) {
n = list[idx];
sendbuf[idx * number + component] = Data[number * n + component];
Data[number*n+component] = 0.0; // Set the data value to zero once it's in the buffer!
Data[number * n + component] =
0.0; // Set the data value to zero once it's in the buffer!
}
}
}
extern "C" void ScaLBL_UnpackDenD3Q7(int *list, int count, double *recvbuf, int number, double *Data, int N){
extern "C" void ScaLBL_UnpackDenD3Q7(int *list, int count, double *recvbuf,
int number, double *Data, int N) {
//....................................................................................
// Unack distribution from the recv buffer
// Sum to the existing density value
@ -72,7 +91,8 @@ extern "C" void ScaLBL_UnpackDenD3Q7(int *list, int count, double *recvbuf, int
}
}
extern "C" void ScaLBL_D3Q7_Reflection_BC_z(int *list, double *dist, int count, int Np){
extern "C" void ScaLBL_D3Q7_Reflection_BC_z(int *list, double *dist, int count,
int Np) {
int n;
for (int idx = 0; idx < count; idx++) {
n = list[idx];
@ -81,7 +101,8 @@ extern "C" void ScaLBL_D3Q7_Reflection_BC_z(int *list, double *dist, int count,
}
}
extern "C" void ScaLBL_D3Q7_Reflection_BC_Z(int *list, double *dist, int count, int Np){
extern "C" void ScaLBL_D3Q7_Reflection_BC_Z(int *list, double *dist, int count,
int Np) {
int n;
for (int idx = 0; idx < count; idx++) {
n = list[idx];
@ -89,8 +110,8 @@ extern "C" void ScaLBL_D3Q7_Reflection_BC_Z(int *list, double *dist, int count,
dist[5 * Np + n] = f6;
}
}
extern "C" void ScaLBL_D3Q7_Init(char *ID, double *f_even, double *f_odd, double *Den, int Nx, int Ny, int Nz)
{
extern "C" void ScaLBL_D3Q7_Init(char *ID, double *f_even, double *f_odd,
double *Den, int Nx, int Ny, int Nz) {
int n, N;
N = Nx * Ny * Nz;
double value;
@ -106,8 +127,7 @@ extern "C" void ScaLBL_D3Q7_Init(char *ID, double *f_even, double *f_odd, double
f_even[2 * N + n] = 0.1111111111111111 * value; //double(100*n)+4.f;
f_odd[2 * N + n] = 0.1111111111111111 * value; //double(100*n)+5.f;
f_even[3 * N + n] = 0.1111111111111111 * value; //double(100*n)+6.f;
}
else{
} else {
for (int q = 0; q < 3; q++) {
f_even[q * N + n] = -1.0;
f_odd[q * N + n] = -1.0;
@ -118,8 +138,8 @@ extern "C" void ScaLBL_D3Q7_Init(char *ID, double *f_even, double *f_odd, double
}
//*************************************************************************
extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd, int Nx, int Ny, int Nz)
{
extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd,
int Nx, int Ny, int Nz) {
int i, j, k, n, nn, N;
// distributions
double f1, f2, f3, f4, f5, f6;
@ -145,7 +165,8 @@ extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd, in
// Retrieve odd distributions from neighboring nodes (swap convention)
//........................................................................
nn = n + 1; // neighbor index (pull convention)
if (!(i+1<Nx)) nn -= Nx; // periodic BC along the x-boundary
if (!(i + 1 < Nx))
nn -= Nx; // periodic BC along the x-boundary
//if (i+1<Nx){
f2 = disteven[N + nn]; // pull neighbor for distribution 2
if (!(f2 < 0.0)) {
@ -155,7 +176,8 @@ extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd, in
//}
//........................................................................
nn = n + Nx; // neighbor index (pull convention)
if (!(j+1<Ny)) nn -= Nx*Ny; // Perioidic BC along the y-boundary
if (!(j + 1 < Ny))
nn -= Nx * Ny; // Perioidic BC along the y-boundary
//if (j+1<Ny){
f4 = disteven[2 * N + nn]; // pull neighbor for distribution 4
if (!(f4 < 0.0)) {
@ -165,7 +187,8 @@ extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd, in
}
//........................................................................
nn = n + Nx * Ny; // neighbor index (pull convention)
if (!(k+1<Nz)) nn -= Nx*Ny*Nz; // Perioidic BC along the z-boundary
if (!(k + 1 < Nz))
nn -= Nx * Ny * Nz; // Perioidic BC along the z-boundary
//if (k+1<Nz){
f6 = disteven[3 * N + nn]; // pull neighbor for distribution 6
if (!(f6 < 0.0)) {
@ -178,9 +201,8 @@ extern "C" void ScaLBL_D3Q7_Swap(char *ID, double *disteven, double *distodd, in
}
//*************************************************************************
extern "C" void ScaLBL_D3Q7_Density(char *ID, double *disteven, double *distodd, double *Den,
int Nx, int Ny, int Nz)
{
extern "C" void ScaLBL_D3Q7_Density(char *ID, double *disteven, double *distodd,
double *Den, int Nx, int Ny, int Nz) {
char id;
int n;
double f0, f1, f2, f3, f4, f5, f6;

View File

@ -1,7 +1,9 @@
// CPU Functions for D3Q7 Lattice Boltzmann Methods
// Boundary Conditions
extern "C" void ScaLBL_Solid_Dirichlet_D3Q7(double *dist,double *BoundaryValue,int *BounceBackDist_list,int *BounceBackSolid_list,int N){
extern "C" void ScaLBL_Solid_Dirichlet_D3Q7(double *dist, double *BoundaryValue,
int *BounceBackDist_list,
int *BounceBackSolid_list, int N) {
int idx;
int iq, ib;
@ -11,12 +13,15 @@ extern "C" void ScaLBL_Solid_Dirichlet_D3Q7(double *dist,double *BoundaryValue,i
ib = BounceBackSolid_list[idx];
value_b = BoundaryValue[ib]; //get boundary value from a solid site
value_q = dist[iq];
dist[iq] = -1.0*value_q + value_b*0.25;//NOTE 0.25 is the speed of sound for D3Q7 lattice
dist[iq] =
-1.0 * value_q +
value_b * 0.25; //NOTE 0.25 is the speed of sound for D3Q7 lattice
}
}
extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist,double *BoundaryValue,int *BounceBackDist_list,int *BounceBackSolid_list,int N){
extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist, double *BoundaryValue,
int *BounceBackDist_list,
int *BounceBackSolid_list, int N) {
int idx;
int iq, ib;
@ -30,6 +35,26 @@ extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist,double *BoundaryValue,int
}
}
extern "C" void ScaLBL_Solid_DirichletAndNeumann_D3Q7(double *dist,double *BoundaryValue,int* BoundaryLabel,int *BounceBackDist_list,int *BounceBackSolid_list,int N){
int idx;
int iq,ib;
double value_b,value_b_label,value_q;
for (idx=0; idx<N; idx++){
iq = BounceBackDist_list[idx];
ib = BounceBackSolid_list[idx];
value_b = BoundaryValue[ib];//get boundary value from a solid site
value_b_label = BoundaryLabel[ib];//get boundary label (i.e. type of BC) from a solid site
value_q = dist[iq];
if (value_b_label==1){//Dirichlet BC
dist[iq] = -1.0*value_q + value_b*0.25;//NOTE 0.25 is the speed of sound for D3Q7 lattice
}
if (value_b_label==2){//Neumann BC
dist[iq] = value_q + value_b;
}
}
}
extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epsilon_LB, double tau, double rho0,double den_scale, double h, double time_conv,
int *BounceBackDist_list, int *BounceBackSolid_list, int *FluidBoundary_list,
@ -63,25 +88,35 @@ extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta
nsx = SolidGrad[ifluidBC + 0 * Np];
nsy = SolidGrad[ifluidBC + 1 * Np];
nsz = SolidGrad[ifluidBC + 2 * Np];
E_mag_normal = Ex*nsx+Ey*nsy+Ez*nsz;//magnitude of electric field in the direction normal to solid nodes
E_mag_normal =
Ex * nsx + Ey * nsy +
Ez *
nsz; //magnitude of electric field in the direction normal to solid nodes
//compute tangential electric field
Etx = Ex - E_mag_normal * nsx;
Ety = Ey - E_mag_normal * nsy;
Etz = Ez - E_mag_normal * nsz;
ubx = -epsilon_LB*value_b*Etx/(nu_LB*rho0)*time_conv*time_conv/(h*h*1.0e-12)/den_scale;
uby = -epsilon_LB*value_b*Ety/(nu_LB*rho0)*time_conv*time_conv/(h*h*1.0e-12)/den_scale;
ubz = -epsilon_LB*value_b*Etz/(nu_LB*rho0)*time_conv*time_conv/(h*h*1.0e-12)/den_scale;
ubx = -epsilon_LB * value_b * Etx / (nu_LB * rho0) * time_conv *
time_conv / (h * h * 1.0e-12) / den_scale;
uby = -epsilon_LB * value_b * Ety / (nu_LB * rho0) * time_conv *
time_conv / (h * h * 1.0e-12) / den_scale;
ubz = -epsilon_LB * value_b * Etz / (nu_LB * rho0) * time_conv *
time_conv / (h * h * 1.0e-12) / den_scale;
//compute bounce-back distribution
LB_weight = lattice_weight[idx];
cx = lattice_cx[idx];
cy = lattice_cy[idx];
cz = lattice_cz[idx];
dist[iq] = value_q - 2.0*LB_weight*rho0*cs2_inv*(cx*ubx+cy*uby+cz*ubz);
dist[iq] = value_q - 2.0 * LB_weight * rho0 * cs2_inv *
(cx * ubx + cy * uby + cz * ubz);
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Poisson_Potential_BC_z(int *list, double *dist, double Vin, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAeven_Poisson_Potential_BC_z(int *list,
double *dist,
double Vin, int count,
int Np) {
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
double f0 = dist[n];
@ -96,7 +131,10 @@ extern "C" void ScaLBL_D3Q7_AAeven_Poisson_Potential_BC_z(int *list, double *dis
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Poisson_Potential_BC_Z(int *list, double *dist, double Vout, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAeven_Poisson_Potential_BC_Z(int *list,
double *dist,
double Vout,
int count, int Np) {
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
double f0 = dist[n];
@ -111,7 +149,11 @@ extern "C" void ScaLBL_D3Q7_AAeven_Poisson_Potential_BC_Z(int *list, double *dis
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Poisson_Potential_BC_z(int *d_neighborList, int *list, double *dist, double Vin, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAodd_Poisson_Potential_BC_z(int *d_neighborList,
int *list,
double *dist,
double Vin, int count,
int Np) {
int nread, nr5;
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
@ -139,7 +181,11 @@ extern "C" void ScaLBL_D3Q7_AAodd_Poisson_Potential_BC_z(int *d_neighborList, in
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Poisson_Potential_BC_Z(int *d_neighborList, int *list, double *dist, double Vout, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAodd_Poisson_Potential_BC_Z(int *d_neighborList,
int *list,
double *dist,
double Vout, int count,
int Np) {
int nread, nr6;
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
@ -167,8 +213,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Poisson_Potential_BC_Z(int *d_neighborList, in
}
}
extern "C" void ScaLBL_Poisson_D3Q7_BC_z(int *list, int *Map, double *Psi, double Vin, int count)
{
extern "C" void ScaLBL_Poisson_D3Q7_BC_z(int *list, int *Map, double *Psi,
double Vin, int count) {
int idx, n, nm;
for (idx = 0; idx < count; idx++) {
@ -178,8 +224,8 @@ extern "C" void ScaLBL_Poisson_D3Q7_BC_z(int *list, int *Map, double *Psi, doubl
}
}
extern "C" void ScaLBL_Poisson_D3Q7_BC_Z(int *list, int *Map, double *Psi, double Vout, int count)
{
extern "C" void ScaLBL_Poisson_D3Q7_BC_Z(int *list, int *Map, double *Psi,
double Vout, int count) {
int idx, n, nm;
for (idx = 0; idx < count; idx++) {
@ -189,7 +235,10 @@ extern "C" void ScaLBL_Poisson_D3Q7_BC_Z(int *list, int *Map, double *Psi, doubl
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Concentration_BC_z(int *list, double *dist, double Cin, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Concentration_BC_z(int *list,
double *dist,
double Cin, int count,
int Np) {
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
double f0 = dist[n];
@ -204,7 +253,10 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Concentration_BC_z(int *list, double *dis
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Concentration_BC_Z(int *list, double *dist, double Cout, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Concentration_BC_Z(int *list,
double *dist,
double Cout,
int count, int Np) {
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
double f0 = dist[n];
@ -219,7 +271,11 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Concentration_BC_Z(int *list, double *dis
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Concentration_BC_z(int *d_neighborList, int *list, double *dist, double Cin, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Concentration_BC_z(int *d_neighborList,
int *list,
double *dist,
double Cin, int count,
int Np) {
int nread, nr5;
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
@ -247,7 +303,11 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Concentration_BC_z(int *d_neighborList, in
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Concentration_BC_Z(int *d_neighborList, int *list, double *dist, double Cout, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Concentration_BC_Z(int *d_neighborList,
int *list,
double *dist,
double Cout, int count,
int Np) {
int nread, nr6;
for (int idx = 0; idx < count; idx++) {
int n = list[idx];
@ -275,7 +335,10 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Concentration_BC_Z(int *d_neighborList, in
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_BC_z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_BC_z(int *list, double *dist,
double FluxIn, double tau,
double *VelocityZ, int count,
int Np) {
//NOTE: FluxIn is the inward flux
double f0, f1, f2, f3, f4, f5, f6;
double fsum_partial;
@ -293,13 +356,16 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_BC_z(int *list, double *dist, double
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*f6-0.5*uz*fsum_partial/tau)/(1.0-0.5/tau+0.5*uz/tau);
f5 = (FluxIn + (1.0 - 0.5 / tau) * f6 - 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau + 0.5 * uz / tau);
dist[6 * Np + n] = f5;
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_BC_Z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_BC_Z(int *list, double *dist,
double FluxIn, double tau,
double *VelocityZ, int count,
int Np) {
//NOTE: FluxIn is the inward flux
double f0, f1, f2, f3, f4, f5, f6;
double fsum_partial;
@ -317,12 +383,16 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_BC_Z(int *list, double *dist, double
uz = VelocityZ[n];
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+0.5*uz*fsum_partial/tau)/(1.0-0.5/tau-0.5*uz/tau);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 + 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau - 0.5 * uz / tau);
dist[5 * Np + n] = f6;
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_z(int *d_neighborList, int *list,
double *dist, double FluxIn,
double tau, double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
double f0, f1, f2, f3, f4, f5, f6;
double fsum_partial;
@ -351,7 +421,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_z(int *d_neighborList, int *list,
fsum_partial = f0 + f1 + f2 + f3 + f4 + f6;
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*f6-0.5*uz*fsum_partial/tau)/(1.0-0.5/tau+0.5*uz/tau);
f5 = (FluxIn + (1.0 - 0.5 / tau) * f6 - 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau + 0.5 * uz / tau);
// Unknown distributions
nr5 = d_neighborList[n + 4 * Np];
@ -359,7 +430,10 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_z(int *d_neighborList, int *list,
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_Z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np){
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_Z(int *d_neighborList, int *list,
double *dist, double FluxIn,
double tau, double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
double f0, f1, f2, f3, f4, f5, f6;
double fsum_partial;
@ -389,7 +463,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_Z(int *d_neighborList, int *list,
fsum_partial = f0 + f1 + f2 + f3 + f4 + f5;
uz = VelocityZ[n];
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+0.5*uz*fsum_partial/tau)/(1.0-0.5/tau-0.5*uz/tau);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 + 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau - 0.5 * uz / tau);
// unknown distributions
nr6 = d_neighborList[n + 5 * Np];
@ -397,8 +472,10 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_BC_Z(int *d_neighborList, int *list,
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_Diff_BC_z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_Diff_BC_z(int *list, double *dist,
double FluxIn, double tau,
double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
double f0, f1, f2, f3, f4, f5, f6;
@ -415,13 +492,16 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_Diff_BC_z(int *list, double *dist, d
fsum_partial = f0 + f1 + f2 + f3 + f4 + f6;
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*(f6+uz*fsum_partial))/(1.0-0.5/tau)/(1.0-uz);
f5 = (FluxIn + (1.0 - 0.5 / tau) * (f6 + uz * fsum_partial)) /
(1.0 - 0.5 / tau) / (1.0 - uz);
dist[6 * Np + n] = f5;
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_Diff_BC_Z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_Diff_BC_Z(int *list, double *dist,
double FluxIn, double tau,
double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
double f0, f1, f2, f3, f4, f5, f6;
@ -438,14 +518,17 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_Diff_BC_Z(int *list, double *dist, d
fsum_partial = f0 + f1 + f2 + f3 + f4 + f5;
uz = VelocityZ[n];
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*(f5-uz*fsum_partial))/(1.0-0.5/tau)/(1.0+uz);
f6 = (FluxIn + (1.0 - 0.5 / tau) * (f5 - uz * fsum_partial)) /
(1.0 - 0.5 / tau) / (1.0 + uz);
dist[5 * Np + n] = f6;
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_z(int *d_neighborList,
int *list, double *dist,
double FluxIn, double tau,
double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int n;
int nread, nr5;
@ -476,7 +559,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_z(int *d_neighborList, int *l
fsum_partial = f0 + f1 + f2 + f3 + f4 + f6;
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*(f6+uz*fsum_partial))/(1.0-0.5/tau)/(1.0-uz);
f5 = (FluxIn + (1.0 - 0.5 / tau) * (f6 + uz * fsum_partial)) /
(1.0 - 0.5 / tau) / (1.0 - uz);
// Unknown distributions
nr5 = d_neighborList[n + 4 * Np];
@ -484,8 +568,11 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_z(int *d_neighborList, int *l
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_Z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_Z(int *d_neighborList,
int *list, double *dist,
double FluxIn, double tau,
double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int n;
int nread, nr5;
@ -514,7 +601,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_Z(int *d_neighborList, int *l
fsum_partial = f0 + f1 + f2 + f3 + f4 + f6;
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*(f6+uz*fsum_partial))/(1.0-0.5/tau)/(1.0-uz);
f5 = (FluxIn + (1.0 - 0.5 / tau) * (f6 + uz * fsum_partial)) /
(1.0 - 0.5 / tau) / (1.0 - uz);
// Unknown distributions
nr5 = d_neighborList[n + 4 * Np];
@ -522,10 +610,9 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_Diff_BC_Z(int *d_neighborList, int *l
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvc_BC_z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvc_BC_z(
int *list, double *dist, double FluxIn, double tau, double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
double f0, f1, f2, f3, f4, f5, f6;
@ -543,13 +630,15 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvc_BC_z(int *list, double *dis
fsum_partial = f0 + f1 + f2 + f3 + f4 + f6;
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*f6-0.5*uz*fsum_partial/tau)/(1.0-0.5/tau+0.5*uz/tau);
f5 = (FluxIn + (1.0 - 0.5 / tau) * f6 - 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau + 0.5 * uz / tau);
dist[6 * Np + n] = f5;
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvc_BC_Z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvc_BC_Z(
int *list, double *dist, double FluxIn, double tau, double *VelocityZ,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
double f0, f1, f2, f3, f4, f5, f6;
@ -566,13 +655,15 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvc_BC_Z(int *list, double *dis
fsum_partial = f0 + f1 + f2 + f3 + f4 + f5;
uz = VelocityZ[n];
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+0.5*uz*fsum_partial/tau)/(1.0-0.5/tau-0.5*uz/tau);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 + 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau - 0.5 * uz / tau);
dist[5 * Np + n] = f6;
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_z(
int *d_neighborList, int *list, double *dist, double FluxIn, double tau,
double *VelocityZ, int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
int nread, nr5;
@ -601,7 +692,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_z(int *d_neighborList, in
fsum_partial = f0 + f1 + f2 + f3 + f4 + f6;
uz = VelocityZ[n];
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*f6-0.5*uz*fsum_partial/tau)/(1.0-0.5/tau+0.5*uz/tau);
f5 = (FluxIn + (1.0 - 0.5 / tau) * f6 - 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau + 0.5 * uz / tau);
// Unknown distributions
nr5 = d_neighborList[n + 4 * Np];
@ -609,8 +701,9 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_z(int *d_neighborList, in
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_Z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_Z(
int *d_neighborList, int *list, double *dist, double FluxIn, double tau,
double *VelocityZ, int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
int nread, nr6;
@ -639,7 +732,8 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_Z(int *d_neighborList, in
fsum_partial = f0 + f1 + f2 + f3 + f4 + f5;
uz = VelocityZ[n];
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+0.5*uz*fsum_partial/tau)/(1.0-0.5/tau-0.5*uz/tau);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 + 0.5 * uz * fsum_partial / tau) /
(1.0 - 0.5 / tau - 0.5 * uz / tau);
// unknown distributions
nr6 = d_neighborList[n + 5 * Np];
@ -647,9 +741,10 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvc_BC_Z(int *d_neighborList, in
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, double *ElectricField_Z,
double Di, double zi, double Vt, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_z(
int *list, double *dist, double FluxIn, double tau, double *VelocityZ,
double *ElectricField_Z, double Di, double zi, double Vt, int count,
int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
double f0, f1, f2, f3, f4, f5, f6;
@ -670,15 +765,17 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_z(int *list, double
Ez = ElectricField_Z[n];
uEPz = zi * Di / Vt * Ez;
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+(0.5*uz/tau+uEPz)*fsum_partial)/(1.0-0.5/tau-0.5*uz/tau-uEPz);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 +
(0.5 * uz / tau + uEPz) * fsum_partial) /
(1.0 - 0.5 / tau - 0.5 * uz / tau - uEPz);
dist[5 * Np + n] = f6;
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, double *ElectricField_Z,
double Di, double zi, double Vt, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_z(
int *d_neighborList, int *list, double *dist, double FluxIn, double tau,
double *VelocityZ, double *ElectricField_Z, double Di, double zi, double Vt,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
int nread, nr5;
@ -711,7 +808,9 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_z(int *d_neighborList
Ez = ElectricField_Z[n];
uEPz = zi * Di / Vt * Ez;
//...................................................
f5 =(FluxIn+(1.0-0.5/tau)*f6-(0.5*uz/tau+uEPz)*fsum_partial)/(1.0-0.5/tau+0.5*uz/tau+uEPz);
f5 = (FluxIn + (1.0 - 0.5 / tau) * f6 -
(0.5 * uz / tau + uEPz) * fsum_partial) /
(1.0 - 0.5 / tau + 0.5 * uz / tau + uEPz);
// Unknown distributions
nr5 = d_neighborList[n + 4 * Np];
@ -719,9 +818,10 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_z(int *d_neighborList
}
}
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_Z(int *list, double *dist, double FluxIn, double tau, double *VelocityZ, double *ElectricField_Z,
double Di, double zi, double Vt, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_Z(
int *list, double *dist, double FluxIn, double tau, double *VelocityZ,
double *ElectricField_Z, double Di, double zi, double Vt, int count,
int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
double f0, f1, f2, f3, f4, f5, f6;
@ -742,13 +842,16 @@ extern "C" void ScaLBL_D3Q7_AAeven_Ion_Flux_DiffAdvcElec_BC_Z(int *list, double
Ez = ElectricField_Z[n];
uEPz = zi * Di / Vt * Ez;
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+(0.5*uz/tau+uEPz)*fsum_partial)/(1.0-0.5/tau-0.5*uz/tau-uEPz);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 +
(0.5 * uz / tau + uEPz) * fsum_partial) /
(1.0 - 0.5 / tau - 0.5 * uz / tau - uEPz);
dist[5 * Np + n] = f6;
}
}
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_Z(int *d_neighborList, int *list, double *dist, double FluxIn, double tau, double *VelocityZ, double *ElectricField_Z,
double Di, double zi, double Vt, int count, int Np)
{
extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_Z(
int *d_neighborList, int *list, double *dist, double FluxIn, double tau,
double *VelocityZ, double *ElectricField_Z, double Di, double zi, double Vt,
int count, int Np) {
//NOTE: FluxIn is the inward flux
int idx, n;
int nread, nr6;
@ -781,21 +884,12 @@ extern "C" void ScaLBL_D3Q7_AAodd_Ion_Flux_DiffAdvcElec_BC_Z(int *d_neighborList
Ez = ElectricField_Z[n];
uEPz = zi * Di / Vt * Ez;
//...................................................
f6 =(FluxIn+(1.0-0.5/tau)*f5+(0.5*uz/tau+uEPz)*fsum_partial)/(1.0-0.5/tau-0.5*uz/tau-uEPz);
f6 = (FluxIn + (1.0 - 0.5 / tau) * f5 +
(0.5 * uz / tau + uEPz) * fsum_partial) /
(1.0 - 0.5 / tau - 0.5 * uz / tau - uEPz);
// unknown distributions
nr6 = d_neighborList[n + 5 * Np];
dist[nr6] = f6;
}
}

View File

@ -1,12 +1,25 @@
/*
Copyright 2013--2018 James E. McClure, Virginia Polytechnic & State University
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
// Basic cuda functions callable from C/C++ code
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mm_malloc.h>
extern "C" int ScaLBL_SetDevice(int rank){
return 0;
}
extern "C" int ScaLBL_SetDevice(int rank) { return 0; }
extern "C" void ScaLBL_AllocateZeroCopy(void **address, size_t size) {
//cudaMalloc(address,size);
@ -28,22 +41,21 @@ extern "C" void ScaLBL_AllocateDeviceMemory(void** address, size_t size){
}
}
extern "C" void ScaLBL_FreeDeviceMemory(void* pointer){
_mm_free(pointer);
}
extern "C" void ScaLBL_FreeDeviceMemory(void *pointer) { _mm_free(pointer); }
extern "C" void ScaLBL_CopyToDevice(void* dest, const void* source, size_t size){
extern "C" void ScaLBL_CopyToDevice(void *dest, const void *source,
size_t size) {
// cudaMemcpy(dest,source,size,cudaMemcpyHostToDevice);
memcpy(dest, source, size);
}
extern "C" void ScaLBL_CopyToHost(void *dest, const void *source, size_t size) {
// cudaMemcpy(dest,source,size,cudaMemcpyDeviceToHost);
memcpy(dest, source, size);
}
extern "C" void ScaLBL_CopyToZeroCopy(void* dest, const void* source, size_t size){
extern "C" void ScaLBL_CopyToZeroCopy(void *dest, const void *source,
size_t size) {
// cudaMemcpy(dest,source,size,cudaMemcpyDeviceToHost);
memcpy(dest, source, size);
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More