Commit 1cfefa24 authored by David Moxey's avatar David Moxey

Merge branch 'master' into feature/remove-loki

parents 8e7645c9 e598a95c
......@@ -6,6 +6,14 @@ v4.5.0
**NekMesh**:
- Add periodic boundary condition meshing in 2D (!733)
- Adjust boundary layer thickness in corners in 2D (!739)
- Add non-O BL meshing in 2D (!757)
**Library**
- Added in sum factorisation version for pyramid expansions and orthogonal
expansion in pyramids (!750)
**FieldConvert**:
- Add input module for Semtex field files (!777)
**Documentation**:
- Added the developer-guide repository as a submodule (!751)
......@@ -13,19 +21,41 @@ v4.5.0
v4.4.1
------
**Library**
- Remove m_offset_elmt_id and GetOffsetElmtId which fixed problems in 2D when
quad elements are listed before tri elements (!758)
- Remove the duplicate output of errorutil (!756)
- Fix BLAS CMake dependencies (!763)
- Fix interpolation issue with Lagrange basis functions (!768)
- Fix issue with average fields not working with different polynomial order
fields (!776)
- Fix rounding of integer parameters (!774)
- Fix Hdf5 output in FilterFieldConvert (!781)
- Fixed extreme memory consumption of Interpolator when interpolating from pts
to fld or between different meshes (!783)
- Fix deadlock with HDF5 input (!786)
- Fix missing entriess in LibUtilities::kPointsTypeStr (!792)
- Fix compiler warnings with CommDataType (!793)
**FieldConvert**:
**FieldConvert:**
- Fix issue with field ordering in the interppointdatatofld module (!754)
- Fix issue with FieldConvert when range flag used (!761)
- Fix issue when using output-points combined with noequispaced (!775)
- Fix equispacedoutput for 3DH1D with triangles (!787)
**NekMesh**:
- Fix memory consumption issue with Gmsh output (!747, !762)
- Rework meshing control so that if possible viewable meshes will be dumped
when some part of the system fails (!756)
- Add manifold meshing option (!756)
- Fix issue with older rea input files (!765)
- Fix memory leak in variational optimiser, add small optimisations (!785)
- Check the dimensionality of the CAD system before running the 2D generator (!780)
**FieldConvert:**
- Fix issue with field ordering in the interppointdatatofld module (!754)
**IncNavierStokesSolver**
- Fix an initialisation issue when using an additional advective field (!779)
**Packaging**
- Added missing package for FieldUtils library (!755)
v4.4.0
------
......
......@@ -44,7 +44,9 @@ project. It's a pretty simple process:
diff and are not quite ready to merge, use the `[WIP]` tag in the title to
prevent your code from being accidentally merged.
5. Put a comment in the MR saying that it's ready to be merged.
6. Respond to any comments in the code review.
6. If your branch is a minor fix that could appear in the next patch release,
then add the `Proposed patch` label to the merge request.
7. Respond to any comments in the code review.
## Submission checklist
- Did you add regression tests (for fixes) or unit tests and/or normal tests for
......@@ -155,6 +157,78 @@ stick to the following process:
- Once feedback received from the branch author (if necessary) and reviewers are
happy, the branch will be merged.
## Release branches
Nektar++ releases are versioned in the standard form `x.y.z` where `x` is a
major release, `y` a minor release and `z` a patch release:
- major releases are extremely infrequent (on the order of every 2-3 years) and
denote major changes in functionality and the API;
- minor releases occur around twice per year and contain new features with minor
API changes;
- patch releases are targeted on roughly a monthly basis and are intended to
fix minor issues in the code.
The repository contains a number of _release branches_ named `release/x.y` for
each minor release, which are intended to contain **fixes and very minor
changes** from `master` and which form the next patch release. This allows us to
use `master` for the next minor release, whilst still having key fixes in patch
releases.
### Cherry-picking process
Any branches that are marked with the `Proposed patch` label should follow the
following additional steps to cherry pick commits into the `release/x.y` branch.
1. If the branch is on a remote other than `nektar/nektar`, make sure that's
added to your local repository.
2. On a local terminal, run `git fetch --all` to pull the latest changes. It's
important for the commands below that you do this _before_ you merge the
branch into `master`.
3. Merge the branch into master as usual using GitLab.
4. Switch to the appropriate branch with `git checkout release/x.y` and update
with `git pull`.
5. Now check the list of commits to cherry-pick.
```bash
git log --oneline --no-merges --reverse origin/master..REMOTE/fix/BRANCHNAME
```
where `REMOTE` is the remote on which the branch lives and `BRANCHNAME` is
the fix branch. If the list is empty, you probably did a `git fetch` after
you merged the branch into `master`; in this case use `origin/master^`.
6. If you're happy with the list (compare to the MR list on the GitLab MR if
necessary), cherry-pick the commits with the command:
```bash
git cherry-pick -x $(git rev-list --no-merges --reverse origin/master..REMOTE/fix/BRANCHNAME)
```
7. It's likely you'll encounter some conflicts, particularly with the
`CHANGELOG`. To fix these:
- `git status` to see what's broken
- Fix appropriately
- `git commit -a` to commit your fix
- `git cherry-pick --continue`
8. If everything becomes horribly broken, `git cherry-pick --abort`.
9. Once you're happy, `git push` to send your changes back to GitLab.
Steps 5 and 6 can be simplified by creating a script
```bash
#!/bin/bash
src=$1
logopts="--oneline --no-merges --reverse"
commits=`git log $logopts master..$1 | cut -f 1 -d " " | xargs`
echo "Will cherry-pick the following commits: $commits"
echo "Press ENTER to continue..."
read
cherryopts="-x --allow-empty --allow-empty-message"
git cherry-pick $cherryopts $commits
```
which accepts the name of the source branch as the sole argument.
## Formatting guidelines
Nektar++ uses C++, a language notorious for being easy to make obtuse and
difficult to follow code. To hopefully alleviate this problem, there are a
......
......@@ -10,13 +10,14 @@ OPTION(NEKTAR_USE_FFTW
"Use FFTW routines for performing the Fast Fourier Transform." OFF)
IF (NEKTAR_USE_FFTW)
# Set some common FFTW search paths.
# Set some common FFTW search paths for the library.
SET(FFTW_SEARCH_PATHS $ENV{LD_LIBRARY_PATH} $ENV{FFTW_HOME}/lib)
FIND_LIBRARY(FFTW_LIBRARY NAMES fftw3 fftw3f PATHS ${FFTW_SEARCH_PATHS})
IF (FFTW_LIBRARY)
GET_FILENAME_COMPONENT(FFTW_PATH ${FFTW_LIBRARY} PATH)
SET(FFTW_INCLUDE_DIR ${FFTW_PATH}/../include CACHE FILEPATH "FFTW include directory.")
FIND_PATH(FFTW_INCLUDE_DIR NAMES fftw3.h CACHE FILEPATH
"FFTW include directory.")
IF (FFTW_LIBRARY AND FFTW_INCLUDE_DIR)
SET(BUILD_FFTW OFF)
ELSE()
SET(BUILD_FFTW ON)
......@@ -55,9 +56,18 @@ IF (NEKTAR_USE_FFTW)
MESSAGE(STATUS "Found FFTW: ${FFTW_LIBRARY}")
SET(FFTW_CONFIG_INCLUDE_DIR ${FFTW_INCLUDE_DIR})
ENDIF()
# Test if FFTW path is a system path. Only add to include path if not an
# implicitly defined CXX include path (due to GCC 6.x now providing its own
# version of some C header files and -isystem reorders include paths).
GET_FILENAME_COMPONENT(X ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES} ABSOLUTE)
GET_FILENAME_COMPONENT(Y ${FFTW_INCLUDE_DIR} ABSOLUTE)
IF (NOT Y MATCHES ".*${X}.*")
INCLUDE_DIRECTORIES(SYSTEM ${FFTW_INCLUDE_DIR})
ENDIF()
MARK_AS_ADVANCED(FFTW_LIBRARY)
MARK_AS_ADVANCED(FFTW_INCLUDE_DIR)
ENDIF( NEKTAR_USE_FFTW )
INCLUDE_DIRECTORIES(SYSTEM ${FFTW_INCLUDE_DIR})
MARK_AS_ADVANCED(FFTW_LIBRARY)
MARK_AS_ADVANCED(FFTW_INCLUDE_DIR)
......@@ -757,6 +757,7 @@ INPUT = @CMAKE_SOURCE_DIR@/docs/doxygen/ \
@CMAKE_SOURCE_DIR@/library/LibUtilities/ \
@CMAKE_SOURCE_DIR@/library/StdRegions/ \
@CMAKE_SOURCE_DIR@/library/SpatialDomains/ \
@CMAKE_SOURCE_DIR@/library/Collections/ \
@CMAKE_SOURCE_DIR@/library/LocalRegions/ \
@CMAKE_SOURCE_DIR@/library/MultiRegions/ \
@CMAKE_SOURCE_DIR@/library/GlobalMapping/ \
......
\chapter{FieldConvert}
\label{s:utilities:fieldconvert}
FieldConvert is a utility embedded in \nekpp with the primary aim of
allowing the user to convert the \nekpp output binary files (.chk and
.fld) into a format which can be read by two common visualisation
softwares: Paraview/VisIt (.vtu format) or Tecplot/VisIt (.dat or .plt
formats). FieldConvert also allows the user to manipulate the \nekpp
output binary files by using some additional modules which can be
called with the option \inltt{-m} which stands for
\inltt{m}odule. Note that another flag, \inltt{-r} (which stand for
\inltt{r}ange) allows the user to specify a sub-range of the domain on
which the conversion or manipulation of the \nekpp output binary files
will be performed.
FieldConvert is a utility embedded in \nekpp with the primary aim of allowing
the user to convert the \nekpp output binary files (\inltt{.chk} and
\inltt{.fld}) into formats which can be read by common visualisation and
post-processing software, primarily Paraview/VisIt (in unstructured VTK
\inltt{.vtu} format) or Tecplot/VisIt (in ASCII \inltt{.dat} or binary
\inltt{.plt} formats). FieldConvert also allows the user to manipulate the
\nekpp output binary files by using some additional modules which can be called
with the option \inltt{-m} which stands for \inltt{m}odule. Note that another
flag, \inltt{-r} (which stand for \inltt{r}ange) allows the user to specify a
sub-range of the domain on which the conversion or manipulation of the \nekpp
output binary files will be performed.
Almost all of the FieldConvert functionalities can be run in parallel if \nekpp
is compiled using MPI (see the installation documentation for additional info on
......@@ -19,6 +19,49 @@ how to implement \nekpp using MPI). \footnote{Modules that do not have parallel
%
%
%
\section{Basic usage}
FieldConvert expects at least one input specification (such as a session file
and its corresponding field file) and one output specification. These are
specified on the command line as
%
\begin{lstlisting}[style=BashInputStyle]
FieldConvert in1.xml in2.fld out.dat
\end{lstlisting}
%
These can be combined with a processing module by adding the \inltt{-m} command
line option. There can be more than one module specified, and they can appear
anywhere in the command line arguments, although the order of execution is
inferred from their order in the command line. For example, the command
%
\begin{lstlisting}[style=BashInputStyle]
FieldConvert in1.xml -m module1 in2.fld -m module2 out.dat
\end{lstlisting}
%
causes \inltt{in1.xml} and \inltt{in2.fld} to be read, followed by the
\inltt{module1} processing module, the \inltt{module2} processing module, and
finally output to the \inltt{out.dat} Tecplot file.
\subsection{Input formats}
FieldConvert supports XML and FLD-format files as produced by \nekpp. It also
supports the reading of data files from two external spectral element codes:
\emph{Semtex}\footnote{http://users.monash.edu.au/~bburn/semtex.html} and
\emph{Nek5000}\footnote{https://nek5000.mcs.anl.gov}. These files can be
directly converted to \nekpp format files by using the command
%
\begin{lstlisting}[style=BashInputStyle]
FieldConvert input.fld output.fld
\end{lstlisting}
%
Note that even though the \inltt{.fld} extension is typically associated with
\nekpp files, FieldConvert can automatically identify \emph{Semtex} and
\emph{Nek5000} input field files.
To use these files in a simulation, or to post-process the results of a
simulation, an appropriate mesh must also be defined in the \nekpp XML format.
\nm can be used to convert these input files to XML, as outlined in
section~\ref{s:utilities:nekmesh}.
\section{Convert .fld / .chk files into Paraview, VisIt or Tecplot format}
\label{s:utilities:fieldconvert:sub:convert}
To convert the \nekpp output binary files (.chk and .fld) into a
......
......@@ -917,7 +917,7 @@ class BwdTrans_SumFac_Prism : public Operator
{
Blas::Dgemm('N', 'N', m_nquad2, m_numElmt, m_nmodes2-i,
1.0, m_base2.get()+mode*m_nquad2, m_nquad2,
&input[0]+mode1, totmodes, 0.0,
input.get()+mode1, totmodes, 0.0,
&wsp[j*m_nquad2*m_numElmt*m_nmodes0+ cnt],
m_nquad2);
mode1 += m_nmodes2-i;
......@@ -1017,5 +1017,168 @@ OperatorKey BwdTrans_SumFac_Prism::m_type = GetOperatorFactory().
OperatorKey(ePrism, eBwdTrans, eSumFac,false),
BwdTrans_SumFac_Prism::create, "BwdTrans_SumFac_Prism");
/**
* @brief Backward transform operator using sum-factorisation (Pyr)
*/
class BwdTrans_SumFac_Pyr : public Operator
{
public:
OPERATOR_CREATE(BwdTrans_SumFac_Pyr)
virtual ~BwdTrans_SumFac_Pyr()
{
}
virtual void operator()(
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &output1,
Array<OneD, NekDouble> &output2,
Array<OneD, NekDouble> &wsp)
{
ASSERTL1(wsp.num_elements() == m_wspSize,
"Incorrect workspace size");
// Assign second half of workspace for 2nd DGEMM operation.
int totmodes = m_stdExp->GetNcoeffs();
Array<OneD, NekDouble> wsp2
= wsp + m_nmodes0*m_nmodes1*m_nquad2*m_numElmt;
Vmath::Zero(m_nmodes0*m_nmodes1*m_nquad2*m_numElmt, wsp, 1);
int i = 0;
int j = 0;
int mode = 0;
int mode1 = 0;
int cnt = 0;
for (i = 0; i < m_nmodes0; ++i)
{
for (j = 0; j < m_nmodes1; ++j, ++cnt)
{
int ijmax = max(i,j);
Blas::Dgemm('N', 'N', m_nquad2, m_numElmt, m_nmodes2-ijmax,
1.0, m_base2.get()+mode*m_nquad2, m_nquad2,
input.get()+mode1, totmodes, 0.0,
wsp.get() + cnt*m_nquad2*m_numElmt, m_nquad2);
mode += m_nmodes2-ijmax;
mode1 += m_nmodes2-ijmax;
}
//increment mode in case order1!=order2
for(j = m_nmodes1; j < m_nmodes2-i; ++j)
{
int ijmax = max(i,j);
mode += m_nmodes2-ijmax;
}
}
// vertex mode - currently (1+c)/2 x (1-b)/2 x (1-a)/2
// component is evaluated
if(m_sortTopVertex)
{
for(i = 0; i < m_numElmt; ++i)
{
// top singular vertex
// (1+c)/2 x (1+b)/2 x (1-a)/2 component
Blas::Daxpy(m_nquad2, input[1+i*totmodes],
m_base2.get() + m_nquad2, 1,
&wsp[m_nquad2*m_numElmt] + i*m_nquad2, 1);
// top singular vertex
// (1+c)/2 x (1-b)/2 x (1+a)/2 component
Blas::Daxpy(m_nquad2, input[1+i*totmodes],
m_base2.get() + m_nquad2, 1,
&wsp[m_nmodes1*m_nquad2*m_numElmt]
+ i*m_nquad2, 1);
// top singular vertex
// (1+c)/2 x (1+b)/2 x (1+a)/2 component
Blas::Daxpy(m_nquad2, input[1+i*totmodes],
m_base2.get() + m_nquad2, 1,
&wsp[(m_nmodes1+1)*m_nquad2*m_numElmt]
+ i*m_nquad2, 1);
}
}
// Perform summation over '1' direction
mode = 0;
for(i = 0; i < m_nmodes0; ++i)
{
Blas::Dgemm('N', 'T', m_nquad1, m_nquad2*m_numElmt, m_nmodes1,
1.0, m_base1.get(), m_nquad1,
wsp.get() + mode*m_nquad2*m_numElmt,
m_nquad2*m_numElmt,
0.0, wsp2.get() + i*m_nquad1*m_nquad2*m_numElmt,
m_nquad1);
mode += m_nmodes1;
}
// Perform summation over '0' direction
Blas::Dgemm('N', 'T', m_nquad0, m_nquad1*m_nquad2*m_numElmt,
m_nmodes0, 1.0, m_base0.get(), m_nquad0,
wsp2.get(), m_nquad1*m_nquad2*m_numElmt,
0.0, output.get(), m_nquad0);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
const int m_nquad2;
const int m_nmodes0;
const int m_nmodes1;
const int m_nmodes2;
Array<OneD, const NekDouble> m_base0;
Array<OneD, const NekDouble> m_base1;
Array<OneD, const NekDouble> m_base2;
bool m_sortTopVertex;
private:
BwdTrans_SumFac_Pyr(
vector<StdRegions::StdExpansionSharedPtr> pCollExp,
CoalescedGeomDataSharedPtr pGeomData)
: Operator (pCollExp, pGeomData),
m_nquad0 (m_stdExp->GetNumPoints(0)),
m_nquad1 (m_stdExp->GetNumPoints(1)),
m_nquad2 (m_stdExp->GetNumPoints(2)),
m_nmodes0 (m_stdExp->GetBasisNumModes(0)),
m_nmodes1 (m_stdExp->GetBasisNumModes(1)),
m_nmodes2 (m_stdExp->GetBasisNumModes(2)),
m_base0 (m_stdExp->GetBasis(0)->GetBdata()),
m_base1 (m_stdExp->GetBasis(1)->GetBdata()),
m_base2 (m_stdExp->GetBasis(2)->GetBdata())
{
m_wspSize = m_numElmt*m_nmodes0*m_nquad2*(m_nmodes1 + m_nquad1);
if(m_stdExp->GetBasis(0)->GetBasisType()
== LibUtilities::eModified_A)
{
m_sortTopVertex = true;
}
else
{
m_sortTopVertex = false;
}
}
};
/// Factory initialisation for the BwdTrans_SumFac_Pyr operator
OperatorKey BwdTrans_SumFac_Pyr::m_type = GetOperatorFactory().
RegisterCreatorFunction(
OperatorKey(ePyramid, eBwdTrans, eSumFac,false),
BwdTrans_SumFac_Pyr::create, "BwdTrans_SumFac_Pyr");
}
}
......@@ -422,6 +422,101 @@ void PrismIProduct(bool sortTopVertex, int numElmt,
}
/**
*
*/
void PyrIProduct(bool sortTopVertex, int numElmt,
int nquad0, int nquad1, int nquad2,
int nmodes0, int nmodes1, int nmodes2,
const Array<OneD, const NekDouble> &base0,
const Array<OneD, const NekDouble> &base1,
const Array<OneD, const NekDouble> &base2,
const Array<OneD, const NekDouble> &jac,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
int totmodes = LibUtilities::StdPyrData::getNumberOfCoefficients(
nmodes0,nmodes1,nmodes2);
int totpoints = nquad0*nquad1*nquad2;
int cnt;
int mode, mode1;
ASSERTL1(wsp.num_elements() >= numElmt*(nquad1*nquad2*nmodes0 +
nquad2*max(nquad0*nquad1,nmodes0*nmodes1)),
"Insufficient workspace size");
Vmath::Vmul(numElmt*totpoints,jac,1,input,1,wsp,1);
Array<OneD, NekDouble> wsp1 = wsp + numElmt * nquad2
* (max(nquad0*nquad1,
nmodes0*nmodes1));
// Perform iproduct with respect to the '0' direction
Blas::Dgemm('T', 'N', nquad1*nquad2*numElmt, nmodes0, nquad0,
1.0, wsp.get(), nquad0, base0.get(),
nquad0, 0.0, wsp1.get(), nquad1*nquad2*numElmt);
// Inner product with respect to the '1' direction
mode = 0;
for(int i=0; i < nmodes0; ++i)
{
Blas::Dgemm('T', 'N', nquad2*numElmt, nmodes1, nquad1,
1.0, wsp1.get()+ i*nquad1*nquad2*numElmt, nquad1,
base1.get(), nquad1,
0.0, wsp.get() + mode*nquad2*numElmt,nquad2*numElmt);
mode += nmodes1;
}
// Inner product with respect to the '2' direction
mode = mode1 = cnt = 0;
for(int i = 0; i < nmodes0; ++i)
{
for(int j = 0; j < nmodes1; ++j, ++cnt)
{
int ijmax = max(i,j);
Blas::Dgemm('T', 'N', nmodes2-ijmax, numElmt, nquad2,
1.0, base2.get()+mode*nquad2, nquad2,
wsp.get()+cnt*nquad2*numElmt, nquad2,
0.0, output.get()+mode1, totmodes);
mode += nmodes2-ijmax;
mode1 += nmodes2-ijmax;
}
//increment mode in case order1!=order2
for(int j = nmodes1; j < nmodes2; ++j)
{
int ijmax = max(i,j);
mode += nmodes2-ijmax;
}
}
// fix for modified basis for top singular vertex component
// Already have evaluated (1+c)/2 (1-b)/2 (1-a)/2
if(sortTopVertex)
{
for(int n = 0; n < numElmt; ++n)
{
// add in (1+c)/2 (1+b)/2 component
output[1+n*totmodes] += Blas::Ddot(nquad2,
base2.get()+nquad2,1,
&wsp[nquad2*numElmt + n*nquad2],1);
// add in (1+c)/2 (1-b)/2 (1+a)/2 component
output[1+n*totmodes] += Blas::Ddot(nquad2,
base2.get()+nquad2,1,
&wsp[nquad2*nmodes1*numElmt+n*nquad2],1);
// add in (1+c)/2 (1+b)/2 (1+a)/2 component
output[1+n*totmodes] += Blas::Ddot(nquad2,
base2.get()+nquad2,1,
&wsp[nquad2*(nmodes1+1)*numElmt+n*nquad2],1);
}
}
}