1 // @HEADER
2 // ************************************************************************
3 //
4 //               Rapid Optimization Library (ROL) Package
5 //                 Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 //              Drew Kouri   (dpkouri@sandia.gov) and
39 //              Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 /*! \file  materials.hpp
45 */
46 
47 #ifndef MATERIALS_HPP
48 #define MATERIALS_HPP
49 
50 #include "Intrepid_FieldContainer.hpp"
51 
52 /** \class  Materials
53 */
54 
55 template <class Real>
56 class Material {
57 private:
58 
59   int dim_;
60   int tensorMatSize_;
61 
62   bool planeStrain_;
63   Real modulus_;
64   Real poissonRatio_;
65   ROL::Ptr<Intrepid::FieldContainer<Real> > materialTensor_;
66 
67 public:
68 
Material()69   Material() {}
~Material()70   virtual ~Material() {}
71 
InitializeMaterial(const int dim,const bool planeStrain,const Real modulus,const Real poissonRatio)72   virtual void InitializeMaterial(const int dim, const bool planeStrain,
73                                   const Real modulus, const Real poissonRatio) {
74     TEUCHOS_TEST_FOR_EXCEPTION(dim > 3 || dim < 1, std::invalid_argument,
75       ">>> ERROR (InitializeMaterial): dim less than one or greater than three!");
76     dim_          = dim;
77     planeStrain_  = planeStrain;
78     modulus_      = modulus;
79     poissonRatio_ = poissonRatio;
80     if(dim_==1) {
81       tensorMatSize_ = 1;
82     }
83     else if(dim_==2) {
84       tensorMatSize_ = 3;
85     }
86     else {
87       tensorMatSize_ = 6;
88     }
89 
90     ComputeMaterialTensor();
91   }
92 
ComputeMaterialTensor(void)93   void ComputeMaterialTensor(void) {
94     materialTensor_ = ROL::makePtr<Intrepid::FieldContainer<Real>>(tensorMatSize_, tensorMatSize_);
95     materialTensor_ -> initialize(0.0);
96     if(dim_==1) {
97       (*materialTensor_)(0, 0)=modulus_;
98     }
99     else if(dim_==2 && !planeStrain_) {
100       Real one(1), half(0.5);
101       Real factor1 = modulus_ /(one-poissonRatio_*poissonRatio_);
102       (*materialTensor_)(0, 0) = factor1;
103       (*materialTensor_)(0, 1) = factor1 * poissonRatio_;
104       (*materialTensor_)(1, 0) = factor1 * poissonRatio_;
105       (*materialTensor_)(1, 1) = factor1;
106       (*materialTensor_)(2, 2) = factor1 * half * (one-poissonRatio_);
107     }
108     else if(dim_==2 && planeStrain_) {
109       Real one(1), two(2), half(0.5);
110       Real factor2 = modulus_ /(one+poissonRatio_)/(one-two*poissonRatio_);
111       (*materialTensor_)(0, 0) = factor2 * (one-poissonRatio_);
112       (*materialTensor_)(0, 1) = factor2 * poissonRatio_;
113       (*materialTensor_)(1, 0) = factor2 * poissonRatio_;
114       (*materialTensor_)(1, 1) = factor2 * (one-poissonRatio_);
115       (*materialTensor_)(2, 2) = factor2 * half * (one-two*poissonRatio_);
116     }
117     else {
118       Real one(1), two(2), half(0.5);
119       Real lam = modulus_*poissonRatio_/(one+poissonRatio_)/(one-two*poissonRatio_);
120       Real mu = half*modulus_/(one+poissonRatio_);
121       (*materialTensor_)(0, 0) = lam + two*mu;
122       (*materialTensor_)(0, 1) = lam;
123       (*materialTensor_)(0, 2) = lam;
124       (*materialTensor_)(1, 0) = lam;
125       (*materialTensor_)(1, 1) = lam + two*mu;
126       (*materialTensor_)(1, 2) = lam;
127       (*materialTensor_)(2, 0) = lam;
128       (*materialTensor_)(2, 1) = lam;
129       (*materialTensor_)(2, 2) = lam + two*mu;
130       (*materialTensor_)(3, 3) = mu;
131       (*materialTensor_)(4, 4) = mu;
132       (*materialTensor_)(5, 5) = mu;
133     }
134   }
135 
GetMaterialTensor(void) const136   const ROL::Ptr<Intrepid::FieldContainer<Real> > GetMaterialTensor(void) const {
137     return materialTensor_;
138   }
139 
GetMaterialTensorDim(void) const140   int GetMaterialTensorDim(void) const {
141     return tensorMatSize_;
142   }
143 
GetYoungsModulus(void) const144   Real GetYoungsModulus(void) const {
145     return modulus_;
146   }
147 
GetPoissonRatio(void) const148   Real GetPoissonRatio(void) const {
149     return poissonRatio_;
150   }
151 
GetBulkModulus(void) const152   Real GetBulkModulus(void) const { }
153 
GetShearModulus(void) const154   Real GetShearModulus(void) const {
155     Real half(0.5), one(1);
156     return half*modulus_/(one+poissonRatio_);
157   }
158 
CheckMaterialTensor(void)159   void CheckMaterialTensor(void) {
160     std::cout<< *materialTensor_ <<std::endl;
161   }
162 
163 };
164 
165 
166 // new class for topology optimization
167 template<class Real>
168 class Material_SIMP : public Material <Real> {
169 private:
170 
171   Real density_;
172   int powerP_;
173   Real minDensity_;
174 
175 public:
176 
InitializeSIMP(const int dim,const bool planeStrain,const Real modulus,const Real poissonRatio,const Real density,const int powerP,const Real minDensity)177   virtual void InitializeSIMP(const int dim, const bool planeStrain,
178                               const Real modulus, const Real poissonRatio,
179                               const Real density, const int powerP, const Real minDensity) {
180     TEUCHOS_TEST_FOR_EXCEPTION(powerP < 1, std::invalid_argument,
181       ">>> ERROR (InitializeSIMP): SIMP power is less than one!");
182     Material<Real>::InitializeMaterial(dim, planeStrain, modulus, poissonRatio);
183     density_    = density;
184     powerP_     = powerP;
185     minDensity_ = minDensity;
186   }
187 
getSIMPScaleFactor(void) const188   Real getSIMPScaleFactor(void) const {
189     TEUCHOS_TEST_FOR_EXCEPTION(powerP_ < 1, std::invalid_argument,
190       ">>> ERROR (getSIMPScaleFactor): SIMP power is less than one!");
191     Real one(1);
192     return minDensity_ + (one-minDensity_)*std::pow(density_, powerP_);
193   }
194 
getSIMPFirstDerivativeScaleFactor(void) const195   Real getSIMPFirstDerivativeScaleFactor(void) const {
196     TEUCHOS_TEST_FOR_EXCEPTION(powerP_ < 1, std::invalid_argument,
197       ">>> ERROR (getSIMPFirstDerivativeScaleFactor): SIMP power is less than one!");
198     Real one(1);
199     return (one-minDensity_) * powerP_ * (std::pow(density_, powerP_-1));
200   }
201 
getSIMPSecondDerivativeScaleFactor(void) const202   Real getSIMPSecondDerivativeScaleFactor(void) const {
203     TEUCHOS_TEST_FOR_EXCEPTION(powerP_ < 1, std::invalid_argument,
204       ">>> ERROR (getSIMPSecondDerivativeScaleFactor): SIMP power is less than one!");
205     Real one(1), scale(0);
206     if ( powerP_ > 1 ) {
207       scale = (one-minDensity_) * powerP_ * (powerP_-1) * (std::pow(density_, powerP_-2));
208     }
209     return scale;
210   }
211 
setDensity(const Real dens)212   void setDensity(const Real dens) {
213     density_ = dens;
214   }
215 
216   // the following function is not in use
computeScaledMaterialTensor(const Real scale) const217   ROL::Ptr<Intrepid::FieldContainer<Real> > computeScaledMaterialTensor(const Real scale) const {
218     Real zero(0);
219     int TMS = Material<Real>::getMaterialTensorDim();
220     ROL::Ptr<Intrepid::FieldContainer<Real> > scaledMaterialTensor
221       = ROL::makePtr<Intrepid::FieldContainer<Real>>(TMS, TMS);
222     scaledMaterialTensor -> initialize(zero);
223 
224     for(int i=0; i<TMS; i++) {
225       for(int j=0; j<TMS; j++) {
226         (*scaledMaterialTensor)(i, j) = scale * (*Material<Real>::getMaterialTensor())(i, j);
227       }
228     }
229     return scaledMaterialTensor;
230   }
231 
232 };
233 
234 
235 
236 #endif
237 
238