1 /*!
2  * \file  mfront/src/FiniteStrainBehaviourTangentOperatorConversionPath.cxx
3  * \brief
4  * \author Thomas Helfer
5  * \brief 18 juin 2014
6  * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights
7  * reserved.
8  * This project is publicly released under either the GNU GPL Licence
9  * or the CECILL-A licence. A copy of thoses licences are delivered
10  * with the sources of TFEL. CEA or EDF may also distribute this
11  * project under specific licensing conditions.
12  */
13 
14 #include<ostream>
15 #include<algorithm>
16 #include"MFront/FiniteStrainBehaviourTangentOperatorConversionPath.hxx"
17 
18 namespace mfront
19 {
20 
21   FiniteStrainBehaviourTangentOperatorConversionPath::const_iterator
find(const FiniteStrainBehaviourTangentOperatorConversionPath::TangentOperatorFlag t) const22   FiniteStrainBehaviourTangentOperatorConversionPath::find(const FiniteStrainBehaviourTangentOperatorConversionPath::TangentOperatorFlag t) const
23   {
24     return std::find_if(this->begin(),this->end(),[&t](const FiniteStrainBehaviourTangentOperatorConversion& v){
25 	return v.to()==t;
26       });
27   } // end of FiniteStrainBehaviourTangentOperatorConversionPath::find
28 
29   void
getConversionsPath(std::vector<FiniteStrainBehaviourTangentOperatorConversionPath> & r,const TangentOperatorFlag & b,const std::vector<TangentOperatorFlag> & cp,const std::vector<TangentOperatorFlag> & k,const std::vector<FiniteStrainBehaviourTangentOperatorConversion> & converters)30   FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath(std::vector<FiniteStrainBehaviourTangentOperatorConversionPath>& r,
31 									 const TangentOperatorFlag& b,
32 									 const std::vector<TangentOperatorFlag>& cp, //<! current path
33 									 const std::vector<TangentOperatorFlag>& k,
34 									 const std::vector<FiniteStrainBehaviourTangentOperatorConversion>& converters)
35   {
36     using std::find;
37     using std::vector;
38     vector<TangentOperatorFlag> current_path(cp);
39     current_path.push_back(b);
40     for(const auto& c : converters){
41       if(c.from()==b){
42 	if(!((find(k.begin(),k.end(),c.to())!=k.end())||
43 	     (find(cp.begin(),cp.end(),c.to())!=cp.end()))){
44 	  // not an known operator
45 	  vector<FiniteStrainBehaviourTangentOperatorConversionPath> paths;
46 	  FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath(paths,c.to(),current_path,k,converters);
47 	  if(!paths.empty()){
48 	    vector<FiniteStrainBehaviourTangentOperatorConversionPath>::const_iterator pp;
49 	    for(pp=paths.begin();pp!=paths.end();++pp){
50 	      r.push_back(*pp);
51 	      r.back().insert(r.back().begin(),c);
52 	    }
53 	  } else {
54 	    FiniteStrainBehaviourTangentOperatorConversionPath path;
55 	    path.push_back(c);
56 	    r.push_back(path);
57 	  }
58 	}
59       }
60     }
61   } // end of FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath
62 
63   std::vector<FiniteStrainBehaviourTangentOperatorConversionPath>
getConversionsPath(const TangentOperatorFlag & b,const std::vector<TangentOperatorFlag> & k,const std::vector<FiniteStrainBehaviourTangentOperatorConversion> & converters)64   FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath(const TangentOperatorFlag& b,
65 									 const std::vector<TangentOperatorFlag>& k,
66 									 const std::vector<FiniteStrainBehaviourTangentOperatorConversion>& converters)
67   {
68     std::vector<FiniteStrainBehaviourTangentOperatorConversionPath> r;
69     FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath(r,b,k,std::vector<TangentOperatorFlag>(),converters);
70     return r;
71   } // end of FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath
72 
73   FiniteStrainBehaviourTangentOperatorConversionPath
getShortestPath(const std::vector<FiniteStrainBehaviourTangentOperatorConversionPath> & paths,const FiniteStrainBehaviourTangentOperatorConversionPath::TangentOperatorFlag & t)74   FiniteStrainBehaviourTangentOperatorConversionPath::getShortestPath(const std::vector<FiniteStrainBehaviourTangentOperatorConversionPath>& paths,
75 								      const FiniteStrainBehaviourTangentOperatorConversionPath::TangentOperatorFlag& t)
76   {
77     // shortest path
78     FiniteStrainBehaviourTangentOperatorConversionPath path;
79     for(const auto& p : paths){
80       auto pc = p.find(t);
81       if(pc!=p.end()){
82 	++pc;
83 	// we found a conversion path candidate
84 	if(path.empty()){
85 	  // no previous path
86 	  path.insert(path.begin(),p.begin(),pc);
87 	} else {
88 	  // a previous path exists, select the shortest
89 	  const auto l = pc-p.begin();
90 	  if(l<path.size()){
91 	    path.clear();
92 	    path.insert(path.begin(),p.begin(),pc);
93 	  }
94 	}
95       }
96     }
97     return path;
98   } // end of FiniteStrainBehaviourTangentOperatorConversionPath::getShortestPath
99 
100 } // end of namespace mfront
101