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 
45 #ifndef ROL_PDEOPT_ELASTICITYSIMP_OPERATORS_H
46 #define ROL_PDEOPT_ELASTICITYSIMP_OPERATORS_H
47 
48 #include "Intrepid_HGRAD_QUAD_C2_FEM.hpp"
49 #include "Intrepid_HGRAD_QUAD_C1_FEM.hpp"
50 #include "../TOOLS/elasticitySIMP.hpp"
51 
52 template<class Real>
53 class ElasticitySIMPOperators : public ElasticitySIMP <Real> {
54 private:
55   using GO = typename Tpetra::Map<>::global_ordinal_type;
56 
57   Real volFrac_;
58 
59 public:
60 
ElasticitySIMPOperators(const ROL::Ptr<const Teuchos::Comm<int>> & comm,const Teuchos::RCP<Teuchos::ParameterList> & parlist,const ROL::Ptr<std::ostream> & outStream)61   ElasticitySIMPOperators(const ROL::Ptr<const Teuchos::Comm<int> > &comm,
62                           const Teuchos::RCP<Teuchos::ParameterList> &parlist,
63                           const ROL::Ptr<std::ostream> &outStream) {
64     ElasticitySIMPOperators_Initialize(comm, parlist, outStream);
65     this->SetSIMPParallelStructure();
66     this->SetUpLocalIntrepidArrays();
67     this->ComputeLocalSystemMats(true);
68 //Setup DBC information, do not specify any bc sides, use coordinates to determine the BC instead
69     std::vector<GO> dbc_side {};
70     this->SetUpMyDBCInfo(true, dbc_side);
71     this->process_loading_information(parlist);
72 //With new modification on boundary traction, ComputeLocalForceVec should go after SetUpMyBCInfo and process_loading_information
73     //this->AssembleSystemGraph();
74     this->AssembleSystemGraph();
75     this->AssembleSystemMats();
76     this->ComputeLocalForceVec();
77     this->AssembleRHSVector();
78     this->EnforceDBC();
79     this->ConstructSolvers();
80   }
81 
ElasticitySIMPOperators_Initialize(const ROL::Ptr<const Teuchos::Comm<int>> & comm,const Teuchos::RCP<Teuchos::ParameterList> & parlist,const ROL::Ptr<std::ostream> & outStream)82   void ElasticitySIMPOperators_Initialize(const ROL::Ptr<const Teuchos::Comm<int> > &comm,
83                                           const Teuchos::RCP<Teuchos::ParameterList> &parlist,
84                                           const ROL::Ptr<std::ostream> &outStream) {
85     ElasticitySIMP<Real>::ElasticitySIMP_Initialize(comm, parlist, outStream);
86     volFrac_           = parlist->sublist("ElasticityTopoOpt").get<Real>("Volume Fraction");
87     this->initDensity_ = volFrac_;
88   }
89 
90   // construct solvers with new material
constructSolverWithNewMaterial(void)91   void constructSolverWithNewMaterial(void) {
92     bool ifInit = false;
93     {
94     #ifdef ROL_TIMERS
95     Teuchos::TimeMonitor LocalTimer(*SolverUpdateTime_example_PDEOPT_TOOLS_PDEFEM_GLOB);
96     #endif
97     this->ComputeLocalSystemMats(ifInit);
98     this->AssembleSystemMats();
99     this->MatrixRemoveDBC();
100     }
101     this->ConstructSolvers();
102   }
103   //
104 
getPosCell(void) const105   ROL::Ptr<Intrepid::FieldContainer<int> > getPosCell(void) const {
106     return this->meshMgr_->getPosCell();
107   }
108 
ApplyMatAToVec(ROL::Ptr<Tpetra::MultiVector<>> & Ju,const ROL::Ptr<const Tpetra::MultiVector<>> & u)109   void ApplyMatAToVec(ROL::Ptr<Tpetra::MultiVector<> > &Ju,
110                 const ROL::Ptr<const Tpetra::MultiVector<> > &u) {
111     this->matA_dirichlet_->apply(*u, *Ju);
112   }
113 
ApplyJacobian1ToVec(ROL::Ptr<Tpetra::MultiVector<>> & Ju,const ROL::Ptr<const Tpetra::MultiVector<>> & u)114   void ApplyJacobian1ToVec(ROL::Ptr<Tpetra::MultiVector<> > &Ju,
115                      const ROL::Ptr<const Tpetra::MultiVector<> > &u) {
116     #ifdef ROL_TIMERS
117     Teuchos::TimeMonitor LocalTimer(*ConstraintDerivativeTime_example_PDEOPT_TOOLS_PDEFEM_GLOB);
118     #endif
119     this->matA_dirichlet_->apply(*u, *Ju);
120     // Jv is myUniqueMap_
121     // u is myUniqueMap_
122     // v should be myCellMap_
123     //
124     /*
125     ROL::Ptr<Tpetra::MultiVector<> > Ju_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
126     ROL::Ptr<Tpetra::MultiVector<> > u_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
127     Tpetra::Import<> importer(u->getMap(), u_overlap->getMap());
128     u_overlap->doImport(*u, importer, Tpetra::REPLACE);
129     //simply apply matrix to a vector, no need to apply EBC to the vec
130     //this-> ApplyBCToVec (u_overlap);
131     Teuchos::ArrayRCP<const Real> uData = u_overlap->get1dView();
132 
133     Real SIMPScale(0), sum(0), zero(0);
134     Intrepid::FieldContainer<Real> localDisp(this->numLocalDofs_);
135 
136     for(int i=0; i<this->numCells_; i++) {
137       SIMPScale = this->SIMPmaterial_[i]->getSIMPScaleFactor();
138       localDisp.initialize(zero);
139       for(int j=0; j<this->numLocalDofs_; j++) {
140         localDisp(j) = uData[u_overlap->getMap()->getLocalElement(this->cellDofs_(this->myCellIds_[i], j))];
141       }
142       for(int j=0; j<this->numLocalDofs_; j++) {
143         if(this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],j))) {
144           Ju_overlap -> replaceGlobalValue(this->cellDofs_(this->myCellIds_[i], j), 0, localDisp(j));
145         }
146         else {
147           sum = zero;
148           for(int k=0; k<this->numLocalDofs_; k++) {
149             if( !this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],k)) ) {
150               sum += SIMPScale * (*this->gradgradMats0_)(i, j, k) * localDisp(k);
151             }
152           }
153           Ju_overlap -> sumIntoGlobalValue(this->cellDofs_(this->myCellIds_[i], j), 0, sum);
154         }
155       }
156     }
157 
158     Tpetra::Export<> exporter(Ju_overlap->getMap(), Ju->getMap());
159     //Ju->doExport(*Ju_overlap, exporter, Tpetra::REPLACE);
160     Ju->doExport(*Ju_overlap, exporter, Tpetra::ADD);
161     */
162   }
163 
ApplyInverseJacobian1ToVec(ROL::Ptr<Tpetra::MultiVector<>> & InvJu,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const bool ifTrans)164   void ApplyInverseJacobian1ToVec(ROL::Ptr<Tpetra::MultiVector<> > &InvJu,
165                             const ROL::Ptr<const Tpetra::MultiVector<> > &u,
166                             const bool ifTrans) {
167     //Ju is matA->getDomainMap();
168     #ifdef ROL_TIMERS
169     Teuchos::TimeMonitor LocalTimer(*LUSubstitutionTime_example_PDEOPT_TOOLS_PDEFEM_GLOB);
170     #endif
171     this->getSolver(ifTrans)->setB(u);
172     this->getSolver(ifTrans)->setX(InvJu);
173     this->getSolver(ifTrans)->solve();
174   }
175 
ApplyJacobian2ToVec(ROL::Ptr<Tpetra::MultiVector<>> & Jv,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & v)176   void ApplyJacobian2ToVec(ROL::Ptr<Tpetra::MultiVector<> > &Jv,
177                      const ROL::Ptr<const Tpetra::MultiVector<> > &u,
178                      const ROL::Ptr<const Tpetra::MultiVector<> > &v) {
179     // Jv is myUniqueMap_
180     // u is myUniqueMap_
181     // v should be myCellMap_
182     //
183     #ifdef ROL_TIMERS
184     Teuchos::TimeMonitor LocalTimer(*ConstraintDerivativeTime_example_PDEOPT_TOOLS_PDEFEM_GLOB);
185     #endif
186     ROL::Ptr<Tpetra::MultiVector<> > Jv_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
187     ROL::Ptr<Tpetra::MultiVector<> > u_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
188     Tpetra::Import<> importer(u->getMap(), u_overlap->getMap());
189     u_overlap->doImport(*u, importer, Tpetra::REPLACE);
190     //apply BC here, KU
191     this->ApplyBCToVec (u_overlap);
192     Teuchos::ArrayRCP<const Real> uData = u_overlap->get1dView();
193 
194     ROL::Ptr<Tpetra::MultiVector<> > v_local = ROL::makePtr<Tpetra::MultiVector<>>(this->myCellMap_, 1, true);
195     Tpetra::Export<> exporter1(v->getMap(), this->myCellMap_);
196     v_local->doExport(*v, exporter1, Tpetra::REPLACE);
197     Teuchos::ArrayRCP<const Real> vData = v_local->get1dView();
198 
199     Real SIMPDScale(0), localV(0), sum(0), zero(0);
200     Intrepid::FieldContainer<Real> localDisp(this->numLocalDofs_);
201 
202     for(int i=0; i<this->numCells_; i++) {
203       SIMPDScale = this->SIMPmaterial_[i]->getSIMPFirstDerivativeScaleFactor();
204       localV = vData[v_local->getMap()->getLocalElement(this->myCellIds_[i])];
205 
206       localDisp.initialize(zero);
207       for(int j=0; j<this->numLocalDofs_; j++) {
208         localDisp(j) = uData[u_overlap->getMap()->getLocalElement(this->cellDofs_(this->myCellIds_[i], j))];
209       }
210 
211       for(int j=0; j<this->numLocalDofs_; j++) {
212         if(this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],j))) {
213           Jv_overlap -> replaceGlobalValue(this->cellDofs_(this->myCellIds_[i], j), 0, localDisp(j));
214         }
215         else {
216           sum = zero;
217           for(int k=0; k<this->numLocalDofs_; k++) {
218             if( !this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],k)) ) {
219               sum += localV * SIMPDScale * (*this->gradgradMats0_)(i, j, k) * localDisp(k);
220             }
221           }
222           Jv_overlap -> sumIntoGlobalValue(this->cellDofs_(this->myCellIds_[i], j), 0, sum);
223         }
224       }
225     }
226     Tpetra::Export<> exporter2(Jv_overlap->getMap(), Jv->getMap());
227     //Jv->doExport(*Jv_overlap, exporter2, Tpetra::REPLACE);
228     Jv->doExport(*Jv_overlap, exporter2, Tpetra::ADD);
229   }
230 
ApplyAdjointJacobian2ToVec(ROL::Ptr<Tpetra::MultiVector<>> & Jv,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & v)231   void ApplyAdjointJacobian2ToVec (ROL::Ptr<Tpetra::MultiVector<> > &Jv,
232                              const ROL::Ptr<const Tpetra::MultiVector<> > &u,
233                              const ROL::Ptr<const Tpetra::MultiVector<> > &v) {
234     // Jv is myCellMap_
235     // u should be myUniqueMap_
236     // v should be myUniqueMap_
237     //
238     #ifdef ROL_TIMERS
239     Teuchos::TimeMonitor LocalTimer(*ConstraintDerivativeTime_example_PDEOPT_TOOLS_PDEFEM_GLOB);
240     #endif
241     ROL::Ptr<Tpetra::MultiVector<> > u_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
242     Tpetra::Import<> importer1(u->getMap(), u_overlap->getMap());
243     u_overlap->doImport(*u, importer1, Tpetra::REPLACE);
244     //only apply BC to u
245     this->ApplyBCToVec (u_overlap);
246     Teuchos::ArrayRCP<const Real> uData = u_overlap->get1dView();
247 
248     ROL::Ptr<Tpetra::MultiVector<> > v_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
249     Tpetra::Import<> importer2(v->getMap(), v_overlap->getMap());
250     v_overlap->doImport(*v, importer2, Tpetra::REPLACE);
251     //ApplyBCToVec (v_overlap);
252     Teuchos::ArrayRCP<const Real> vData = v_overlap->get1dView();
253 
254     Intrepid::FieldContainer<Real> u_local(this->numLocalDofs_);
255     Intrepid::FieldContainer<Real> v_local(this->numLocalDofs_);
256 
257     Real SIMPDScale(0), sum(0), zero(0);
258     for(int i=0; i<this->numCells_; i++) {
259       SIMPDScale = this->SIMPmaterial_[i]->getSIMPFirstDerivativeScaleFactor();
260       u_local.initialize(zero);
261       v_local.initialize(zero);
262 
263       for(int j=0; j<this->numLocalDofs_; j++) {
264         u_local(j) = uData[u_overlap->getMap()->getLocalElement(this->cellDofs_(this->myCellIds_[i], j))];
265         v_local(j) = vData[v_overlap->getMap()->getLocalElement(this->cellDofs_(this->myCellIds_[i], j))];
266       }
267 
268       sum = zero;
269       for(int j=0; j<this->numLocalDofs_; j++) {
270         if(this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],j))) {
271           sum += u_local(j) * v_local(j);
272         }
273         else {
274           for(int k=0; k<this->numLocalDofs_; k++) {
275             if( !this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],k)) ) {
276               sum += SIMPDScale * (*this->gradgradMats0_)(i, j, k) * v_local(j) * u_local(k);
277             }
278           }
279         }
280       }
281       //put value into myDensityDerivative_
282       Jv -> replaceGlobalValue(this->myCellIds_[i], 0, sum);
283     }
284   }
285 
ApplyAdjointHessian22ToVec(ROL::Ptr<Tpetra::MultiVector<>> & Hvw,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & w)286   void ApplyAdjointHessian22ToVec(ROL::Ptr<Tpetra::MultiVector<> > &Hvw,
287                             const ROL::Ptr<const Tpetra::MultiVector<> > &u,
288                             const ROL::Ptr<const Tpetra::MultiVector<> > &v,
289                             const ROL::Ptr<const Tpetra::MultiVector<> > &w) {
290     // Hvw is myCellMap_
291     // u should be myUniqueMap_
292     // v should be myCellMap_
293     // w shluld be myUniqueMapi_
294     //
295     #ifdef ROL_TIMERS
296     Teuchos::TimeMonitor LocalTimer(*ConstraintDerivativeTime_example_PDEOPT_TOOLS_PDEFEM_GLOB);
297     #endif
298     ROL::Ptr<Tpetra::MultiVector<> > u_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
299     Tpetra::Import<> importer1(u->getMap(), u_overlap->getMap());
300     u_overlap->doImport(*u, importer1, Tpetra::REPLACE);
301     //only apply BC to U
302     this->ApplyBCToVec (u_overlap);
303     Teuchos::ArrayRCP<const Real> uData = u_overlap->get1dView();
304 
305     Tpetra::Export<> exporter(v->getMap(), this->myCellMap_);
306     ROL::Ptr<Tpetra::MultiVector<> > v_local = ROL::makePtr<Tpetra::MultiVector<>>(this->myCellMap_, 1, true);
307     v_local->doExport(*v, exporter, Tpetra::REPLACE);
308     Teuchos::ArrayRCP<const Real> vData = v_local->get1dView();
309 
310     ROL::Ptr<Tpetra::MultiVector<> > w_overlap = ROL::makePtr<Tpetra::MultiVector<>>(this->myOverlapMap_, 1, true);
311     Tpetra::Import<> importer2(w->getMap(), w_overlap->getMap());
312     w_overlap->doImport(*w, importer2, Tpetra::REPLACE);
313     //ApplyBCToVec (w_overlap);
314     Teuchos::ArrayRCP<const Real> wData = w_overlap->get1dView();
315 
316     Intrepid::FieldContainer<Real> u_local(this->numLocalDofs_);
317     Intrepid::FieldContainer<Real> w_local(this->numLocalDofs_);
318 
319     Real SIMPDDScale(0), localV(0), sum(0), zero(0);
320 
321     for(int i=0; i<this->numCells_; i++) {
322       SIMPDDScale = this->SIMPmaterial_[i]->getSIMPSecondDerivativeScaleFactor();
323       localV = vData[v_local->getMap()->getLocalElement(this->myCellIds_[i])];
324 
325       u_local.initialize(zero);
326       w_local.initialize(zero);
327 
328       for(int j=0; j<this->numLocalDofs_; j++) {
329         u_local(j) = uData[u_overlap->getMap()->getLocalElement(this->cellDofs_(this->myCellIds_[i], j))];
330         w_local(j) = wData[w_overlap->getMap()->getLocalElement(this->cellDofs_(this->myCellIds_[i], j))];
331       }
332 
333       sum = zero;
334       for(int j=0; j<this->numLocalDofs_; j++) {
335         if(this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],j))) {
336           sum += u_local(j) * w_local(j);
337         }
338         else {
339           for(int k=0; k<this->numLocalDofs_; k++) {
340             if( !this->check_myGlobalDof_on_boundary(this->cellDofs_(this->myCellIds_[i],k)) ) {
341               sum += localV * SIMPDDScale * (*this->gradgradMats0_)(i, j, k) * w_local(j) * u_local(k);
342             }
343           }
344         }
345       }
346       //put value into myDensityDerivative_
347       Hvw -> replaceGlobalValue(this->myCellIds_[i], 0, sum);
348     }
349   }
350 
351 }; // class ElasticitySIMPOperators
352 
353 #endif
354