16 #if defined(HAVE_POST)
21 #if defined(HAVE_KBIPACK)
24 std::string convertInt(
int number);
27 template <
class Type>
class PosetCat {
29 virtual ~PosetCat() {}
31 virtual bool lessThan(
const Type &t2)
const = 0;
33 friend bool operator<(
const Type &t1,
const Type &t2)
35 return t1.lessThan(t2);
37 friend bool operator>(
const Type &t1,
const Type &t2)
39 return !t1.lessThan(t2);
41 friend bool operator==(
const Type &t1,
const Type &t2)
43 if(t1.lessThan(t2) && t2.lessThan(t1))
return true;
46 friend bool operator!=(
const Type &t1,
const Type &t2)
48 if(t1.lessThan(t2) && t2.lessThan(t1))
return false;
51 friend bool operator<=(
const Type &t1,
const Type &t2)
53 if(t1.lessThan(t2) || t1 == t2)
return true;
56 friend bool operator>=(
const Type &t1,
const Type &t2)
58 if(!t1.lessThan(t2) || t1 == t2)
return true;
64 template <
class V,
class S>
class VectorSpaceCat {
66 virtual ~VectorSpaceCat() {}
69 virtual V &operator+=(
const V &v) = 0;
70 virtual V &operator*=(
const S &s) = 0;
74 friend V
operator+(
const V &v1,
const V &v2)
80 friend V
operator-(
const V &v1,
const V &v2)
92 friend V
operator*(
const V &v,
const S &s) {
return s * v; }
93 friend V operator/(
const V &v,
const S &s)
105 virtual V &
operator-() {
return (*
this) *= (-1.); }
106 virtual V &operator/=(
const S &s)
109 return (*
this *= temp);
111 virtual V &operator-=(
const V &v)
115 return (*
this += temp);
120 class ElemChain :
public PosetCat<ElemChain> {
123 std::vector<MVertex *> _v;
124 std::vector<char> _si;
125 inline void _sortVertexIndices();
126 bool _equalVertices(
const std::vector<MVertex *> &v2)
const;
128 static std::map<GEntity *, std::set<MVertex *, MVertexPtrLessThan>,
134 ElemChain(
int dim, std::vector<MVertex *> &v);
136 int getDim()
const {
return _dim; }
138 MVertex *getMeshVertex(
int i)
const {
return _v.at(i); }
140 int getNumSortedVertices()
const {
return _v.size(); }
141 inline int getSortedVertex(
int i)
const;
143 int getTypeMSH()
const;
144 MElement *createMeshElement()
const;
146 int compareOrientation(
const ElemChain &c2)
const;
147 bool lessThan(
const ElemChain &c2)
const;
149 int getNumBoundaryElemChains()
const;
150 ElemChain getBoundaryElemChain(
int i)
const;
152 bool inEntity(
GEntity *e)
const;
154 static void clearVertexCache() { _vertexCache.clear(); }
155 static int getTypeMSH(
int dim,
int numVertices);
156 static int getNumBoundaries(
int dim,
int numVertices);
157 static void getBoundaryVertices(
int i,
int dim,
int numVertices,
158 const std::vector<MVertex *> &v,
159 std::vector<MVertex *> &vertices);
162 void findEntitiesInPhysicalGroups(
GModel *m,
163 const std::vector<int> &physicalGroups,
164 std::vector<GEntity *> &entities);
167 template <
class C>
class Chain :
public VectorSpaceCat<Chain<C>, C> {
172 std::map<ElemChain, C> _elemChains;
176 Chain<C> _getTraceOrProject(
const std::vector<GEntity *> &entities,
181 typedef typename std::map<ElemChain, C>::iterator ecit;
182 typedef typename std::map<ElemChain, C>::const_iterator cecit;
185 Chain() : _dim(-1), _name(
"") {}
190 Chain(
GModel *m,
int physicalGroup);
193 std::string getName()
const {
return _name; }
194 void setName(std::string name) { _name = name; }
197 int getDim()
const {
return _dim; }
200 bool isZero()
const {
return _elemChains.empty(); }
203 cecit firstElemChain()
const {
return _elemChains.begin(); }
204 cecit lastElemChain()
const {
return _elemChains.end(); }
207 void addMeshElement(
MElement *e, C coeff = 1);
208 void addElemChain(
const ElemChain &
c, C coeff = 1);
211 Chain<C> &operator+=(
const Chain<C> &chain);
212 Chain<C> &operator*=(
const C &coeff);
215 C getCoefficient(
const ElemChain &c2)
const;
219 C getCoefficient(
MElement *e,
int subElement = -1)
const;
226 Chain<C> getTrace(
GModel *m,
int physicalGroup)
const;
227 Chain<C> getTrace(
GModel *m,
const std::vector<int> &physicalGroups)
const;
228 Chain<C> getTrace(
const std::vector<GEntity *> &entities)
const;
232 Chain<C> getProject(
GModel *m,
int physicalGroup)
const;
233 Chain<C> getProject(
GModel *m,
const std::vector<int> &physicalGroups)
const;
234 Chain<C> getProject(
const std::vector<GEntity *> &entities)
const;
246 int addToModel(
GModel *m,
bool post =
true,
247 int physicalNumRequest = -1)
const;
250 template <
class C> Chain<C>::Chain(
GModel *m,
int physicalGroup)
253 std::vector<int> groups(1, physicalGroup);
254 std::vector<GEntity *> entities;
255 findEntitiesInPhysicalGroups(m, groups, entities);
257 for(std::size_t i = 0; i < entities.size(); i++) {
267 template <
class C> C Chain<C>::getCoefficient(
const ElemChain &c2)
const
269 cecit it = _elemChains.find(c2);
270 if(it != _elemChains.end())
271 return it->second * c2.compareOrientation(it->first);
276 template <
class C> C Chain<C>::getCoefficient(
MElement *e,
int subElement)
const
278 if(this->getDim() == e->
getDim()) {
280 return this->getCoefficient(ec);
282 if(subElement == -1)
return 0;
283 std::vector<MVertex *> v;
284 if(this->getDim() == 0) {
286 v = std::vector<MVertex *>(1, e->
getVertex(subElement));
288 else if(this->getDim() == 1) {
293 else if(this->getDim() == 2) {
303 ElemChain ec(this->getDim(), v);
304 return this->getCoefficient(ec);
307 template <
class C> C incidence(
const Chain<C> &
c1,
const Chain<C> &c2)
310 if(
c1.getDim() != c2.getDim())
return incidence;
311 for(
typename Chain<C>::cecit it =
c1.firstElemChain();
312 it !=
c1.lastElemChain(); it++) {
313 incidence += it->second * c2.getCoefficient(it->first);
316 Msg::Debug(
"%d-chains \'%s\' and \'%s\' have incidence %d",
c1.getDim(),
317 c1.getName().c_str(), c2.getName().c_str(), incidence);
322 template <
class C> Chain<C> boundary(
const ElemChain &
c)
325 for(
int i = 0; i <
c.getNumBoundaryElemChains(); i++) {
327 if(
c.getDim() == 1 && i == 0) coeff = -1;
328 result.addElemChain(
c.getBoundaryElemChain(i), coeff);
336 for(cecit it = _elemChains.begin(); it != _elemChains.end(); it++) {
337 C coeff = it->second;
338 result += boundary<C>(it->first) * coeff;
341 Msg::Info(
"The boundary chain is zero element in C%d", result.getDim());
346 Chain<C> Chain<C>::getTrace(
GModel *m,
int physicalGroup)
const
348 std::vector<int> groups(1, physicalGroup);
349 return this->getTrace(m, groups);
353 Chain<C> Chain<C>::getProject(
GModel *m,
int physicalGroup)
const
355 std::vector<int> groups(1, physicalGroup);
356 return this->getProject(m, groups);
360 Chain<C> Chain<C>::getTrace(
GModel *m,
361 const std::vector<int> &physicalGroups)
const
363 std::vector<GEntity *> entities;
364 findEntitiesInPhysicalGroups(m, physicalGroups, entities);
365 if(entities.empty())
return Chain<C>();
366 return this->_getTraceOrProject(entities,
true);
370 Chain<C> Chain<C>::getProject(
GModel *m,
371 const std::vector<int> &physicalGroups)
const
373 std::vector<GEntity *> entities;
374 findEntitiesInPhysicalGroups(m, physicalGroups, entities);
375 if(entities.empty())
return Chain<C>();
376 return this->_getTraceOrProject(entities,
false);
380 Chain<C> Chain<C>::_getTraceOrProject(
const std::vector<GEntity *> &entities,
384 for(cecit it = _elemChains.begin(); it != _elemChains.end(); it++) {
385 bool inDomain =
false;
386 for(std::size_t i = 0; i < entities.size(); i++) {
387 if(it->first.inEntity(entities.at(i))) {
392 if(inDomain && trace) result.addElemChain(it->first, it->second);
393 if(!inDomain && !trace) result.addElemChain(it->first, it->second);
399 Chain<C> Chain<C>::getTrace(
const std::vector<GEntity *> &entities)
const
401 return this->_getTraceOrProject(entities,
true);
405 Chain<C> Chain<C>::getProject(
const std::vector<GEntity *> &entities)
const
407 return this->_getTraceOrProject(entities,
false);
410 template <
class C>
void Chain<C>::addMeshElement(
MElement *e, C coeff)
413 this->addElemChain(ce, coeff);
416 template <
class C>
void Chain<C>::addElemChain(
const ElemChain &
c, C coeff)
418 if(coeff == 0)
return;
419 if(_dim != -1 && _dim !=
c.getDim()) {
420 Msg::Error(
"Cannot add elementrary %d-chain to %d-chain",
c.getDim(), _dim);
423 if(_dim == -1) _dim =
c.getDim();
424 std::pair<ecit, bool> ii = _elemChains.insert(std::make_pair(
c, coeff));
426 ii.first->second += coeff *
c.compareOrientation(ii.first->first);
427 if(ii.first->second == 0) _elemChains.erase(ii.first);
431 template <
class C> Chain<C> &Chain<C>::operator+=(
const Chain<C> &chain)
433 for(cecit it = chain.firstElemChain(); it != chain.lastElemChain(); it++)
434 this->addElemChain(it->first, it->second);
438 template <
class C> Chain<C> &Chain<C>::operator*=(
const C &coeff)
443 for(ecit it = _elemChains.begin(); it != _elemChains.end(); it++)
449 int Chain<C>::addToModel(
GModel *m,
bool post,
int physicalNumRequest)
const
452 Msg::Info(
"A chain is zero element of C%d, not added to the model",
457 std::string name = _name;
459 if(name.size() > 128) name.resize(128);
461 std::vector<MElement *> elements;
462 std::map<int, std::vector<double> > data;
463 int dim = this->getDim();
465 for(cecit it = this->firstElemChain(); it != this->lastElemChain(); it++) {
466 MElement *e = it->first.createMeshElement();
467 C coeff = it->second;
468 elements.push_back(e);
469 if(dim > 0 && coeff < 0) e->
reverse();
473 for(
int i = 1; i < abs(coeff); i++) {
474 MElement *ecopy = it->first.createMeshElement();
475 if(dim > 0 && coeff < 0) ecopy->
reverse();
476 elements.push_back(ecopy);
478 if(dim > 0) coeff = abs(coeff);
480 std::vector<double> coeffs(1, coeff);
481 data[e->
getNum()] = coeffs;
485 int entityNum = *std::max_element(max, max + 4) + 1;
487 int physicalNum = *std::max_element(max, max + 4) + 1;
488 if(physicalNumRequest > -1 && physicalNumRequest < physicalNum)
489 Msg::Warning(
"Requested chain physical group number already taken. Using "
491 else if(physicalNumRequest > -1 && physicalNumRequest >= physicalNum)
492 physicalNum = physicalNumRequest;
494 std::map<int, std::vector<MElement *> > entityMap;
495 entityMap[entityNum] = elements;
496 std::map<int, std::map<int, std::string> > physicalMap;
497 std::map<int, std::string> physicalInfo;
498 physicalInfo[physicalNum] = name;
499 physicalMap[entityNum] = physicalInfo;
503 #if defined(HAVE_POST)
506 std::string pnum = convertInt(physicalNum);
507 std::string postname = pnum +
"=" + name;
508 PView *view =
new PView(postname,
"ElementData", m, data, 0., 1);