openfoam/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C
Mark Olesen 66a100997f COMP: force dlOpen for windows application binaries (#1238)
- when windows portable executables (.exe or .dll) files are loaded,
  their dependent libraries not fully loaded. For OpenFOAM this means
  that the static constructors which are responsible for populating
  run-time selection tables are not triggered, and most of the run-time
  selectable models will simply not be available.

Possible Solution
=================

  Avoid this problem by defining an additional library symbol such as
  the following:

      extern "C" void libName_Load() {}

  in the respective library, and tag this symbol as 'unresolved' for
  the linker so that it will attempt to resolve it at run-time by
  loading the known libraries until it finds it. The link line would
  resemble the following:

      -L/some/path -llibName -ulibName_Load

  Pros:
    - Allows precise control of forced library loading

  Cons:
    - Moderately verbose adjustment of some source files (even with macro
      wrapping for the declaration).
    - Adjustment of numerous Make/options files and somewhat ad hoc
      in nature.
    - Requires additional care when implementing future libraries and/or
      applications.

  - This is the solution taken by the symscape patches (Richard Smith)

Possible Solution
=================

  Avoid this problem by simply force loading all linked libraries.
  This is done by "scraping" the information out of the respective
  Make/options file (after pre-processing) and using that to define
  the library list that will be passed to Foam::dlOpen() at run-time.

  Pros:
    - One-time (very) minimal adjustment of the sources and wmake toolchain
    - Automatically applies to future applications

  Cons:
    - Possibly larger memory footprint of application (since all dependent
      libraries are loaded).
    - Possible impact on startup time (while loading libraries)
    - More sensitive to build failures. Since the options files are
      read and modified based on the existence of the dependent
      libraries as a preprocessor step, if the libraries are initially
      unavailable for the first attempt at building the application,
      the dependencies will be inaccurate for later (successful) builds.

  - This is solution taken by the bluecape patches (Bruno Santos)

Adopted Solution
================

  The approach taken by Bruno was adopted in a modified form since
  this appears to be the most easily maintained.

Additional Notes
================

  It is always possible to solve this problem by defining a corresponding
  'libs (...)' entry in the case system/controlDict, which forces a dlOpen
  of the listed libraries. This is obviously less than ideal for large-scale
  changes, but can work to resolve an individual problem.

  The peldd utility (https://github.com/gsauthof/pe-util), which is
  also packaged as part of MXE could provide yet another alternative.
  Like ldd it can be used to determine the library dependencies of
  binaries or libraries. This information could be used to define an
  additional load layer for Windows.
2019-05-25 19:10:14 +02:00

391 lines
9.4 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
mapFieldsPar
Group
grpPreProcessingUtilities
Description
Maps volume fields from one mesh to another, reading and
interpolating all fields present in the time directory of both cases.
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "meshToMesh.H"
#include "processorPolyPatch.H"
#include "MapMeshes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void mapConsistentMesh
(
const fvMesh& meshSource,
const fvMesh& meshTarget,
const word& mapMethod,
const word& AMIMapMethod,
const word& procMapMethod,
const bool subtract,
const wordRes& selectedFields,
const bool noLagrangian
)
{
Info<< nl << "Consistently creating and mapping fields for time "
<< meshSource.time().timeName() << nl << endl;
meshToMesh interp
(
meshSource,
meshTarget,
mapMethod,
AMIMapMethod,
meshToMesh::procMapMethodNames_[procMapMethod]
);
if (subtract)
{
MapMesh<minusEqOp>
(
interp,
selectedFields,
noLagrangian
);
}
else
{
MapMesh<plusEqOp>
(
interp,
selectedFields,
noLagrangian
);
}
}
void mapSubMesh
(
const fvMesh& meshSource,
const fvMesh& meshTarget,
const HashTable<word>& patchMap,
const wordList& cuttingPatches,
const word& mapMethod,
const word& AMIMapMethod,
const word& procMapMethod,
const bool subtract,
const wordRes& selectedFields,
const bool noLagrangian
)
{
Info<< nl << "Creating and mapping fields for time "
<< meshSource.time().timeName() << nl << endl;
meshToMesh interp
(
meshSource,
meshTarget,
mapMethod,
AMIMapMethod,
patchMap,
cuttingPatches,
meshToMesh::procMapMethodNames_[procMapMethod]
);
if (subtract)
{
MapMesh<minusEqOp>
(
interp,
selectedFields,
noLagrangian
);
}
else
{
MapMesh<plusEqOp>
(
interp,
selectedFields,
noLagrangian
);
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
(
"Map volume fields from one mesh to another"
);
argList::addArgument("sourceCase");
argList::addOption
(
"sourceTime",
"scalar|'latestTime'",
"Specify the source time"
);
argList::addOption
(
"sourceRegion",
"word",
"Specify the source region"
);
argList::addOption
(
"targetRegion",
"word",
"Specify the target region"
);
argList::addBoolOption
(
"consistent",
"Source and target geometry and boundary conditions identical"
);
argList::addOption
(
"mapMethod",
"word",
"Specify the mapping method "
"(direct|mapNearest|cellVolumeWeight|correctedCellVolumeWeight)"
);
argList::addOption
(
"patchMapMethod",
"word",
"Specify the patch mapping method (direct|mapNearest|faceAreaWeight)"
);
argList::addOption
(
"procMapMethod",
"word",
"Specify the processor distribution map method (AABB|LOD)"
);
argList::addBoolOption
(
"subtract",
"Subtract mapped source from target"
);
argList::addOption
(
"fields",
"wordRes",
"Specify single or multiple fields to reconstruct (all by default)."
" Eg, 'T' or '(p T U \"alpha.*\")'"
);
argList::addBoolOption
(
"noLagrangian",
"Skip mapping lagrangian positions and fields"
);
argList args(argc, argv);
#include "foamDlOpenLibs.H"
fileName rootDirTarget(args.rootPath());
fileName caseDirTarget(args.globalCaseName());
const fileName casePath = args[1];
const fileName rootDirSource = casePath.path();
const fileName caseDirSource = casePath.name();
Info<< "Source: " << rootDirSource << " " << caseDirSource << endl;
word sourceRegion = fvMesh::defaultRegion;
if (args.readIfPresent("sourceRegion", sourceRegion))
{
Info<< "Source region: " << sourceRegion << endl;
}
Info<< "Target: " << rootDirTarget << " " << caseDirTarget << endl;
word targetRegion = fvMesh::defaultRegion;
if (args.readIfPresent("targetRegion", targetRegion))
{
Info<< "Target region: " << targetRegion << endl;
}
const bool consistent = args.found("consistent");
word mapMethod = meshToMesh::interpolationMethodNames_
[
meshToMesh::interpolationMethod::imCellVolumeWeight
];
if (args.readIfPresent("mapMethod", mapMethod))
{
Info<< "Mapping method: " << mapMethod << endl;
}
word patchMapMethod;
if (meshToMesh::interpolationMethodNames_.found(mapMethod))
{
// Lookup corresponding AMI method
meshToMesh::interpolationMethod method =
meshToMesh::interpolationMethodNames_[mapMethod];
patchMapMethod =
AMIPatchToPatchInterpolation::interpolationMethodNames_
[
meshToMesh::interpolationMethodAMI(method)
];
}
word procMapMethod =
meshToMesh::procMapMethodNames_
[
meshToMesh::procMapMethod::pmAABB
];
if (args.readIfPresent("procMapMethod", procMapMethod))
{
Info<< "Processor map method: " << procMapMethod << endl;
}
// Optionally override
if (args.readIfPresent("patchMapMethod", patchMapMethod))
{
Info<< "Patch mapping method: " << patchMapMethod << endl;
}
if (patchMapMethod.empty())
{
FatalErrorInFunction
<< "No valid patchMapMethod for method " << mapMethod
<< ". Please supply one through the 'patchMapMethod' option"
<< exit(FatalError);
}
const bool subtract = args.found("subtract");
if (subtract)
{
Info<< "Subtracting mapped source field from target" << endl;
}
// Non-mandatory
const wordRes selectedFields(args.getList<wordRe>("fields", false));
const bool noLagrangian = args.found("noLagrangian");
#include "createTimes.H"
HashTable<word> patchMap;
wordList cuttingPatches;
if (!consistent)
{
IOdictionary mapFieldsDict
(
IOobject
(
"mapFieldsDict",
runTimeTarget.system(),
runTimeTarget,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
);
mapFieldsDict.readEntry("patchMap", patchMap);
mapFieldsDict.readEntry("cuttingPatches", cuttingPatches);
}
#include "setTimeIndex.H"
Info<< "\nCreate meshes\n" << endl;
fvMesh meshSource
(
IOobject
(
sourceRegion,
runTimeSource.timeName(),
runTimeSource
)
);
fvMesh meshTarget
(
IOobject
(
targetRegion,
runTimeTarget.timeName(),
runTimeTarget
)
);
Info<< "Source mesh size: " << meshSource.globalData().nTotalCells() << tab
<< "Target mesh size: " << meshTarget.globalData().nTotalCells()
<< nl << endl;
if (consistent)
{
mapConsistentMesh
(
meshSource,
meshTarget,
mapMethod,
patchMapMethod,
procMapMethod,
subtract,
selectedFields,
noLagrangian
);
}
else
{
mapSubMesh
(
meshSource,
meshTarget,
patchMap,
cuttingPatches,
mapMethod,
patchMapMethod,
procMapMethod,
subtract,
selectedFields,
noLagrangian
);
}
runTimeSource.printExecutionTime(Info);
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //