676 lines
20 KiB
C
676 lines
20 KiB
C
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
|
\\/ M anipulation |
|
|
-------------------------------------------------------------------------------
|
|
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 2 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, write to the Free Software Foundation,
|
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
// Foam header files
|
|
#include "OSspecific.H"
|
|
|
|
// FoamX header files.
|
|
#include "FoamX.H"
|
|
#include "FoamXErrors.H"
|
|
#include "IGeometricFieldImpl.H"
|
|
#include "IDictionaryEntryImpl.H"
|
|
#include "LogEntry.H"
|
|
#include "Paths.H"
|
|
|
|
// Namespaces
|
|
#include "FoamXNameSpaces.H"
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
FoamX::IGeometricFieldImpl::IGeometricFieldImpl
|
|
(
|
|
IGeometricFieldDescriptor_ptr fieldDescriptor,
|
|
IFoamProperties_ptr foamProperties
|
|
)
|
|
:
|
|
internalFieldValue_(NULL)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::IGeometricFieldImpl"
|
|
"(IGeometricFieldDescriptor_ptr fieldDescriptor, "
|
|
"IFoamProperties_ptr foamProperties)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
// Take references to the FieldDescriptor and FoamProperties objects.
|
|
if (CORBA::is_nil(foamProperties))
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_INVALID_ARG,
|
|
"Invalid FoamProperties reference.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
if (CORBA::is_nil(fieldDescriptor))
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_INVALID_ARG,
|
|
"Invalid FieldDescriptor reference.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
foamProperties_ = IFoamProperties::_duplicate(foamProperties);
|
|
fieldDescriptor_ = IGeometricFieldDescriptor::_duplicate
|
|
(
|
|
fieldDescriptor
|
|
);
|
|
|
|
// Get the field name.
|
|
fieldName_ = fieldDescriptor_->name();
|
|
|
|
// Create the internal field value.
|
|
ITypeDescriptor_var fieldType = fieldDescriptor_->fieldTypeDescriptor();
|
|
internalFieldValue_ = new IDictionaryEntryImpl(fieldType);
|
|
if (internalFieldValue_ == NULL)
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_FAIL,
|
|
"Failed to create internal field value "
|
|
"dictionary entry object.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
FoamX::IGeometricFieldImpl::~IGeometricFieldImpl()
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::~IGeometricFieldImpl()";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
// Release internal value and reference level value dictionary entry objects
|
|
if (internalFieldValue_ != NULL)
|
|
{
|
|
internalFieldValue_->_remove_ref();
|
|
}
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
char* FoamX::IGeometricFieldImpl::name()
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::name()";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
// Get name from fieldDescriptor object.
|
|
if (!CORBA::is_nil(fieldDescriptor_))
|
|
{
|
|
return fieldDescriptor_->name();
|
|
}
|
|
else
|
|
{
|
|
return CORBA::string_dup("");
|
|
}
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void FoamX::IGeometricFieldImpl::getInternalFieldValue
|
|
(
|
|
IDictionaryEntry_out internalFieldValue
|
|
)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::getInternalFieldValue"
|
|
"(IDictionaryEntry_out internalFieldValue)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
if (internalFieldValue_ == NULL)
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_UNEXPECTED,
|
|
"Invalid internal field value object.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
internalFieldValue = internalFieldValue_->_this();
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void FoamX::IGeometricFieldImpl::getPatchFieldParameters
|
|
(
|
|
const char* patchName,
|
|
IDictionaryEntry_out patchFields
|
|
)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::getPatchFieldParameters"
|
|
"(const char* patchName, IDictionaryEntry_out patchFields)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
// See if this patch requires extra parameters.
|
|
if
|
|
(
|
|
patchFields_.found(patchName)
|
|
&& patchFields_[patchName]->subElementPtrs().size() > 1
|
|
)
|
|
{
|
|
patchFields = patchFields_[patchName]->_this();
|
|
}
|
|
else
|
|
{
|
|
patchFields = IDictionaryEntry::_nil();
|
|
}
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
// Set the patch field type for the specified patch. Note that the patch
|
|
// field type parameter is the true Foam name and not the patch
|
|
// field descriptor key.
|
|
|
|
void FoamX::IGeometricFieldImpl::addPatch
|
|
(
|
|
const char* patchName,
|
|
const char* patchFieldType
|
|
)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::addPatch"
|
|
"(const char* patchName, const char* patchFieldType)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
log << "Adding patch " << patchName
|
|
<< " to field " << fieldName_ << endl;
|
|
|
|
// Check patch name.
|
|
if (patchFieldNames_.found(patchName))
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_INVALID_ARG,
|
|
"Invalid patch name.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Lookup this type and see if additional parameters are required.
|
|
ITypeDescriptor_var pfDesc;
|
|
foamProperties_->findPatchFieldType(patchFieldType, pfDesc.out());
|
|
|
|
// Make sure that the patch field type name is valid.
|
|
if (CORBA::is_nil(pfDesc))
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_FAIL,
|
|
"Invalid patch field type name '" + word(patchFieldType) + "'.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Set patch field type.
|
|
patchFieldNames_.insert(patchName, patchFieldType);
|
|
|
|
// Get the type descriptor for the extra parameters. May be nil.
|
|
if (!CORBA::is_nil(pfDesc))
|
|
{
|
|
// Create a default DictionaryEntry object.
|
|
IDictionaryEntryImpl* patchDictEntryPtr = new IDictionaryEntryImpl
|
|
(
|
|
pfDesc
|
|
);
|
|
|
|
if (patchDictEntryPtr == NULL)
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_FAIL,
|
|
"Failed to create IDictionaryEntryImpl object.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Bind the field type descriptor to the parameter
|
|
// dictionary entry object.
|
|
patchDictEntryPtr->bindFieldType
|
|
(
|
|
fieldDescriptor_->fieldTypeDescriptor()
|
|
);
|
|
|
|
// Add to map.
|
|
patchFields_.insert(patchName, patchDictEntryPtr);
|
|
}
|
|
|
|
log << "Added patch " << patchName
|
|
<< " to field " << fieldName_ << endl;
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void FoamX::IGeometricFieldImpl::deletePatch(const char* patchName)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::deletePatch(const char* patchName)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
// Check patch name.
|
|
if (!patchFieldNames_.found(patchName))
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_INVALID_ARG,
|
|
"Invalid patch name.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Remove from patch field type map.
|
|
patchFieldNames_.erase(patchFieldNames_.find(patchName));
|
|
|
|
// Remove from patch field parameter map if necessary.
|
|
if (patchFields_.found(patchName))
|
|
{
|
|
HashTable<IDictionaryEntryImpl*>::iterator iter =
|
|
patchFields_.find(patchName);
|
|
patchFields_.erase(iter); // Releases reference.
|
|
}
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void FoamX::IGeometricFieldImpl::setPatchFieldType
|
|
(
|
|
const char* patchName,
|
|
const char* patchFieldType
|
|
)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::setPatchFieldType"
|
|
"(const char* patchName, const char* patchFieldType)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
// Set patch field type if it has changed.
|
|
if
|
|
(
|
|
!patchFieldNames_.found(patchName)
|
|
|| patchFieldType != patchFieldNames_.find(patchName)()
|
|
)
|
|
{
|
|
deletePatch(patchName);
|
|
addPatch(patchName, patchFieldType);
|
|
}
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
CORBA::Boolean FoamX::IGeometricFieldImpl::modified()
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::ICaseServerImpl::modified()";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
if (internalFieldValue_->modified()) return true;
|
|
|
|
for
|
|
(
|
|
ObjRefHashTable<IDictionaryEntryImpl*>::iterator iter =
|
|
patchFields_.begin();
|
|
iter != patchFields_.end();
|
|
++iter
|
|
)
|
|
{
|
|
if (iter()->modified()) return true;
|
|
}
|
|
}
|
|
CATCH_ALL(functionName);
|
|
|
|
return false;
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void FoamX::IGeometricFieldImpl::load(const dictionary& fieldDict)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::load(const dictionary& fieldDict)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
log << "loading field " << fieldName_ << endl;
|
|
|
|
log << "Reading " << fieldDict.name()
|
|
<< " start line " << fieldDict.startLineNumber()
|
|
<< " end line " << fieldDict.endLineNumber() << endl;
|
|
|
|
// Make sure the field dictionary contains the required entries.
|
|
if
|
|
(
|
|
!fieldDict.found("internalField")
|
|
|| !fieldDict.found("boundaryField")
|
|
)
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_FAIL,
|
|
"Malformed field dictionary.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Read the internal field value.
|
|
internalFieldValue_->load(fieldDict.lookup("internalField"));
|
|
|
|
// Open boundary field dictionary.
|
|
const dictionary& boundaryFieldDict(fieldDict.subDict("boundaryField"));
|
|
|
|
// Loop over all defined patch names and read the patch field values.
|
|
wordList patchNames = patchFieldNames_.toc();
|
|
forAll(patchNames, i)
|
|
{
|
|
word patchName(patchNames[i]);
|
|
|
|
if (!boundaryFieldDict.found(patchName))
|
|
{
|
|
// Patch dictionary not found. Bugger.
|
|
log << "Warning : Patch dictionary '" << patchName
|
|
<< "' not found in field dictionary '" << fieldName_
|
|
<< "'." << endl;
|
|
|
|
WarningIn(functionName)
|
|
<< "Patch dictionary '" << patchName
|
|
<< "' not found in field dictionary '" << fieldName_
|
|
<< "'." << endl;
|
|
continue;
|
|
}
|
|
|
|
// Open patch dictionary.
|
|
const dictionary& patchDict(boundaryFieldDict.subDict(patchName));
|
|
|
|
// Make sure the patch dictionary contains the required entries.
|
|
if (!patchDict.found("type"))
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_FAIL,
|
|
"Patch field type not specified for patch '" + patchName
|
|
+ "' in field dictionary '" + fieldName_ + "'.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Read the patch field type. This is the actual type not the key.
|
|
word patchFieldType(patchDict.lookup("type"));
|
|
|
|
// Get the PatchFieldDescriptor object. Search by type.
|
|
ITypeDescriptor_var pfDesc;
|
|
foamProperties_->findPatchFieldType
|
|
(
|
|
patchFieldType.c_str(),
|
|
pfDesc.out()
|
|
);
|
|
|
|
// Make sure that the patch field type name is valid.
|
|
if (CORBA::is_nil(pfDesc))
|
|
{
|
|
log << "Warning : Invalid patch field type '" << patchFieldType
|
|
<< "' for patch '" << patchName
|
|
<< "' in field dictionary '" << fieldName_ << "'."
|
|
<< endl;
|
|
|
|
WarningIn(functionName)
|
|
<< "Invalid patch field type '" << patchFieldType
|
|
<< "' for patch '" << patchName
|
|
<< "' in field dictionary '" << fieldName_ << "'."
|
|
<< endl;
|
|
|
|
continue;
|
|
}
|
|
|
|
// Check that the patch field type is valid for the boundary type
|
|
// specified for this patch.
|
|
word boundaryPatchFieldType = patchFieldNames_[patchName];
|
|
if (patchFieldType != boundaryPatchFieldType)
|
|
{
|
|
log << "Warning : Incorrect patch field type '"
|
|
<< patchFieldType << "' for patch '" << patchName << "'."
|
|
<< endl << " Boundary condition specifies '"
|
|
<< boundaryPatchFieldType
|
|
<< "' for field '" << fieldName_ << "'."
|
|
<< endl;
|
|
|
|
WarningIn(functionName)
|
|
<< "Incorrect patch field type '"
|
|
<< patchFieldType << "' for patch '" << patchName << "'."
|
|
<< endl << " Boundary condition specifies '"
|
|
<< boundaryPatchFieldType
|
|
<< "' for field '" << fieldName_ << "'."
|
|
<< endl;
|
|
}
|
|
|
|
// Set the patch field type. Poss over-ride default?
|
|
patchFieldNames_[patchName] = patchFieldType;
|
|
|
|
// Release any previous patch field parameter object.
|
|
if (patchFields_.found(patchName))
|
|
{
|
|
HashTable<IDictionaryEntryImpl*>::iterator iter =
|
|
patchFields_.find(patchName);
|
|
patchFields_.erase(iter);
|
|
}
|
|
|
|
// Get the type descriptor for the extra parameters. May be nil.
|
|
if (!CORBA::is_nil(pfDesc))
|
|
{
|
|
// Create and initialise a new IDictionaryEntryImpl
|
|
// object for the parameters.
|
|
IDictionaryEntryImpl* patchDictEntryPtr =
|
|
new IDictionaryEntryImpl
|
|
(
|
|
pfDesc
|
|
);
|
|
if (patchDictEntryPtr == NULL)
|
|
{
|
|
throw FoamXError
|
|
(
|
|
E_FAIL,
|
|
"Failed to create patch field parameter "
|
|
"DictionaryEntry Object.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
|
|
// Bind the field type descriptor to the parameter
|
|
// dictionary entry object.
|
|
patchDictEntryPtr->bindFieldType
|
|
(
|
|
fieldDescriptor_->fieldTypeDescriptor()
|
|
);
|
|
|
|
// Load values from dictionary.
|
|
// The extra parameters are defined as dictionary
|
|
// entries. Pass the entire patch dictionary through.
|
|
// Tolerate non-existent dictionary entries.
|
|
// Any missing parameters will get a default value.
|
|
|
|
patchDictEntryPtr->load
|
|
(
|
|
boundaryFieldDict.subDict(patchName),
|
|
true
|
|
);
|
|
|
|
// Add to map.
|
|
patchFields_.insert(patchName, patchDictEntryPtr);
|
|
}
|
|
}
|
|
}
|
|
CATCH_ALL(functionName);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void FoamX::IGeometricFieldImpl::save
|
|
(
|
|
DictionaryWriter& dictWriter,
|
|
const wordList& patchNames
|
|
)
|
|
{
|
|
static const char* functionName =
|
|
"FoamX::IGeometricFieldImpl::save"
|
|
"(DictionaryWriter& dictWriter, const wordList& patchNames)";
|
|
|
|
LogEntry log(functionName, __FILE__, __LINE__);
|
|
|
|
try
|
|
{
|
|
// Validate the dictionary entry items.
|
|
internalFieldValue_->validate();
|
|
|
|
// Construct class name (eg, "volScalarField").
|
|
word className
|
|
(
|
|
word(fieldDescriptor_->geometryDescriptor()->name())
|
|
& word(fieldDescriptor_->fieldTypeDescriptor()->name())
|
|
);
|
|
|
|
dictWriter.writeHeader
|
|
(
|
|
"Field Dictionary",
|
|
className
|
|
);
|
|
|
|
dictWriter.writeEndl();
|
|
|
|
// Get field dimensions from field descriptor.
|
|
DimensionSet fieldDimension = fieldDescriptor_->dimensions();
|
|
dictWriter.writeEntry("dimensions", fieldDimension);
|
|
dictWriter.writeEndl();
|
|
|
|
// Write internal field and reference values.
|
|
dictWriter.writeKeyword("internalField");
|
|
internalFieldValue_->save(dictWriter, false);
|
|
dictWriter.endEntry();
|
|
dictWriter.writeEndl();
|
|
|
|
// Open boundary field sub-dictionary.
|
|
dictWriter.startSubDict("boundaryField");
|
|
|
|
// Loop over all patchs.
|
|
forAll(patchNames, i)
|
|
{
|
|
dictWriter.writeKeyword(patchNames[i]);
|
|
|
|
// Write value only.
|
|
patchFields_[patchNames[i]]->save(dictWriter, false);
|
|
dictWriter.writeEndl();
|
|
|
|
if (i < patchNames.size()-1)
|
|
{
|
|
dictWriter.writeEndl();
|
|
}
|
|
}
|
|
|
|
dictWriter.endSubDict();
|
|
dictWriter.writeEndl();
|
|
dictWriter.writeEndBar();
|
|
}
|
|
catch (FoamXError& ex)
|
|
{
|
|
// Save failed. Remove the duff file.
|
|
if (exists(dictWriter.pathName()))
|
|
{
|
|
rm(dictWriter.pathName());
|
|
}
|
|
|
|
// Bounce exception up to client.
|
|
throw ex;
|
|
}
|
|
catch (...)
|
|
{
|
|
// Save failed. Remove the duff file.
|
|
if (exists(dictWriter.pathName()))
|
|
{
|
|
rm(dictWriter.pathName());
|
|
}
|
|
|
|
throw FoamXError
|
|
(
|
|
E_UNEXPECTED,
|
|
"Unexpected error.",
|
|
functionName,
|
|
__FILE__, __LINE__
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
// ************************************************************************* //
|