Added: class SIMmultiCpl for monolithic coupled simulators

This commit is contained in:
Knut Morten Okstad
2021-02-25 09:34:40 +01:00
parent db16b4209c
commit a88fd0ca40
2 changed files with 200 additions and 0 deletions

137
src/SIM/SIMmultiCpl.C Normal file
View File

@@ -0,0 +1,137 @@
// $Id$
//==============================================================================
//!
//! \file SIMmultiCpl.C
//!
//! \date Feb 12 2021
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Monolithic coupling of multiple simulators.
//!
//==============================================================================
#include "SIMmultiCpl.h"
#include "SIMoutput.h"
#include "Utilities.h"
#include "IFEM.h"
#include "tinyxml.h"
SIMmultiCpl::SIMmultiCpl (const std::vector<SIMoutput*>& sims)
: SIMadmin(*sims.front()), mySims(sims)
{
if (mySims.size() > 1)
for (SIMoutput* sim : mySims)
if (sim == mySims.front())
sim->setMDflag(1);
else if (sim == mySims.back())
sim->setMDflag(2);
else
sim->setMDflag(3);
}
SIMmultiCpl::~SIMmultiCpl ()
{
for (SIMoutput*& sim : mySims)
delete sim;
}
bool SIMmultiCpl::parse (const TiXmlElement* elem)
{
bool results = true;
if (!strcasecmp(elem->Value(),"coupling"))
{
const TiXmlElement* child = elem->FirstChildElement("connection");
for (; child; child = child->NextSiblingElement("connection"))
results &= this->parseConnection(child);
}
else for (SIMbase* sim : mySims)
if (!sim->parse(elem))
return false;
return true;
}
bool SIMmultiCpl::parseConnection (const TiXmlElement* elem)
{
IFEM::cout <<" Parsing <"<< elem->Value() <<">"<< std::endl;
std::string master, slave;
utl::getAttribute(elem,"master",master);
utl::getAttribute(elem,"slave",slave);
SIMinput* mstSim = nullptr;
SIMinput* slvSim = nullptr;
for (SIMoutput* sim : mySims)
if (sim->getEntity(master).size() == 1)
mstSim = sim;
else if (sim->getEntity(slave).size() == 1)
slvSim = sim;
if (!mstSim || !slvSim)
return false;
myCpl.push_back({mstSim,slvSim,
mstSim->getEntity(master).begin(),
slvSim->getEntity(slave).begin()});
IFEM::cout <<"\tMaster point: \""<< master <<"\""<< *myCpl.back().master
<<"\n\tSlave point: \""<< slave <<"\""<< *myCpl.back().slave
<< std::endl;
return true;
}
bool SIMmultiCpl::preprocess (const std::vector<int>& ignored, bool fixDup)
{
// Preprocess the FE model of each sub-simulator
size_t nOffset = 0;
std::vector<int> empty;
std::map<SIMinput*,int> nSubNodes;
for (SIMoutput* sim : mySims)
if (sim->preprocess(nOffset == 0 ? ignored : empty, fixDup))
{
nSubNodes[sim] = nOffset;
nOffset += sim->getNoNodes();
}
else
return false;
int substep = 10 + mySims.size();
this->printHeading(substep);
// Process the inter-sim couplings
std::map<int,int> cplNodes;
for (const SIMcoupling& cpl : myCpl)
{
std::vector<int> mNodes, sNodes;
cpl.mstSim->getTopItemNodes(*cpl.master,mNodes);
cpl.slvSim->getTopItemNodes(*cpl.slave,sNodes);
for (int& n : mNodes) n += nSubNodes[cpl.mstSim];
for (int& n : sNodes) n += nSubNodes[cpl.slvSim];
if (sNodes.size() != mNodes.size())
{
std::cerr <<" *** SIMmultiCpl::preprocess: Mismatching topological items"
<<" for inter-sim coupling "<< sNodes.size() <<" "
<< mNodes.size() << std::endl;
return false;
}
else for (size_t i = 0; i < sNodes.size(); i++)
cplNodes[sNodes[i]] = mNodes[i];
}
IFEM::cout <<"\nCoupling node mapping:";
for (const std::pair<int,int>& cp : cplNodes)
IFEM::cout <<"\n\t"<< cp.first <<" -> "<< cp.second;
IFEM::cout << std::endl;
// Merge the equation systems into one monolithic system
for (SIMoutput* sim : mySims)
if (!mySims.front()->merge(sim,&cplNodes))
return false;
return true;
}

63
src/SIM/SIMmultiCpl.h Normal file
View File

@@ -0,0 +1,63 @@
// $Id$
//==============================================================================
//!
//! \file SIMmultiCpl.h
//!
//! \date Feb 12 2021
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Monolithic coupling of multiple simulators.
//!
//==============================================================================
#ifndef _SIM_MULTI_CPL_H_
#define _SIM_MULTI_CPL_H_
#include "SIMadmin.h"
#include "TopologySet.h"
class SIMoutput;
class SIMinput;
/*!
\brief Class for monolithic coupled simulators.
*/
class SIMmultiCpl : public SIMadmin
{
public:
//! \brief The constructor initializes the array of base %SIM objects.
SIMmultiCpl(const std::vector<SIMoutput*>& sims);
//! \brief The destructor deletes the base %SIM objects.
virtual ~SIMmultiCpl();
using SIMadmin::parse;
//! \brief Parses a data section from an XML document.
virtual bool parse(const TiXmlElement* elem);
//! \brief Performs some pre-processing tasks on the FE model.
//! \param[in] ignored Indices of patches to ignore in the analysis
//! \param[in] fixDup Merge duplicated FE nodes on patch interfaces?
virtual bool preprocess(const std::vector<int>& ignored, bool fixDup);
private:
//! \brief Parses a connection definition from an XML element.
bool parseConnection(const TiXmlElement* elem);
protected:
//! \brief Struct defining an inter-simulator coupling.
struct SIMcoupling
{
SIMinput* mstSim = nullptr; //!< Simulator of the master point
SIMinput* slvSim = nullptr; //!< Simulator of the slave point
TopEntity::const_iterator master; //!< Master point specification
TopEntity::const_iterator slave; //!< Slave point specification
};
std::vector<SIMcoupling> myCpl; //!< Inter-sim coupling definition container
std::vector<SIMoutput*> mySims; //!< Dimension-specific simulator container
};
#endif