@*
MMT.tmpl

Created by Graham Dennis on 2008-12-12.

Copyright (c) 2008-2012, Graham Dennis

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 2 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/>.

*@
@extends xpdeint.Features.Transforms._MMT

@from xpdeint.Geometry.NonUniformDimensionRepresentation import NonUniformDimensionRepresentation

@def description: MMT
@attr $uselib = ['cblas']

@from xpdeint.CallOnceGuards import callOnceGuard

@def includes
  @#
  @super
  @#
#if   defined(CBLAS_MKL)
  #include <mkl.h>
#elif defined(CBLAS_VECLIB)
  #include <Accelerate/Accelerate.h>
#elif defined(CBLAS_ATLAS)
  @# ATLAS CBLAS usually isn't wrapped by an extern "C" block, so we need to.
  extern "C" {
    #include <cblas.h>
  }
#elif defined(CBLAS_GSL)
  #include <gsl/gsl_cblas.h>
#endif
  @#
@end def

@def mainBegin($dict)
  @#

  @if 'mpi' in $simulationBuildVariant
#if defined(CBLAS_VECLIB)
// We are using MPI. If we let vecLib spawn threads then overall performance will suffer
  setenv("VECLIB_MAXIMUM_THREADS", "1", 1);
#endif
  @end if
  @#
  @for dimName, basisDict in $basisMap.items()
    @for field in [field for field in $fields if field.hasDimensionName(dimName)]
      @if field == $geometry
        @continue
      @end if
      @for (fieldDimRep, geometryDimRep) in zip(field.dimensionWithName(dimName).representations, $geometry.dimensionWithName(dimName).representations)
        @if not fieldDimRep or not isinstance(fieldDimRep, NonUniformDimensionRepresentation) or geometryDimRep.arrayName == fieldDimRep.arrayName
          @continue
        @end if
        @if geometryDimRep.runtimeLattice == fieldDimRep.runtimeLattice
memcpy(${fieldDimRep.arrayName}, ${geometryDimRep.arrayName}, sizeof(real)*${geometryDimRep.globalLattice});
memcpy(${fieldDimRep.stepSizeArrayName}, ${geometryDimRep.stepSizeArrayName}, sizeof(real) * ${geometryDimRep.globalLattice});
        @else
for (long _i0=0; _i0 < $fieldDimRep.globalLattice; _i0++) {
  ${fieldDimRep.arrayName}[_i0] = ${geometryDimRep.arrayName}[_i0 * ($geometryDimRep.globalLattice / $fieldDimRep.globalLattice)];
  ${fieldDimRep.stepSizeArrayName}[_i0] = ${geometryDimRep.stepSizeArrayName}[_i0 * ($geometryDimRep.globalLattice / $fieldDimRep.globalLattice)];
}
        @end if
      @end for
    @end for

  @end for
@end def

