• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

AAdapt_InitialCondition.cpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 
00007 #include <cmath>
00008 
00009 #include <Teuchos_CommHelpers.hpp>
00010 
00011 #include "AAdapt_InitialCondition.hpp"
00012 #include "AAdapt_AnalyticFunction.hpp"
00013 #include "Epetra_Comm.h"
00014 #include "Albany_Utils.hpp"
00015 
00016 namespace AAdapt {
00017 
00018 const double pi = 3.141592653589793;
00019 
00020 
00021 Teuchos::RCP<const Teuchos::ParameterList>
00022 getValidInitialConditionParameters(const Teuchos::ArrayRCP<std::string>& wsEBNames) {
00023   Teuchos::RCP<Teuchos::ParameterList> validPL =
00024     rcp(new Teuchos::ParameterList("ValidInitialConditionParams"));;
00025   validPL->set<std::string>("Function", "", "");
00026   Teuchos::Array<double> defaultData;
00027   validPL->set<Teuchos::Array<double> >("Function Data", defaultData, "");
00028 
00029   // Validate element block constant data
00030 
00031   for(int i = 0; i < wsEBNames.size(); i++)
00032 
00033     validPL->set<Teuchos::Array<double> >(wsEBNames[i], defaultData, "");
00034 
00035   // For EBConstant data, we can optionally randomly perturb the IC on each variable some amount
00036 
00037   validPL->set<Teuchos::Array<double> >("Perturb IC", defaultData, "");
00038 
00039   return validPL;
00040 }
00041 
00042 void InitialConditions(const Teuchos::RCP<Epetra_Vector>& soln,
00043                        const Teuchos::ArrayRCP<Teuchos::ArrayRCP<Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> > > >& wsElNodeEqID,
00044                        const Teuchos::ArrayRCP<std::string>& wsEBNames,
00045                        const Teuchos::ArrayRCP<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > > coords,
00046                        const int neq, const int numDim,
00047                        Teuchos::ParameterList& icParams, const bool hasRestartSolution) {
00048   // Called twice, with x and xdot. Different param lists are sent in.
00049   icParams.validateParameters(*AAdapt::getValidInitialConditionParameters(wsEBNames), 0);
00050 
00051   // Default function is Constant, unless a Restart solution vector
00052   // was used, in which case the Init COnd defaults to Restart.
00053   std::string name;
00054 
00055   if(!hasRestartSolution) name = icParams.get("Function", "Constant");
00056 
00057   else                     name = icParams.get("Function", "Restart");
00058 
00059   if(name == "Restart") return;
00060 
00061   // Handle element block specific constant data
00062 
00063   if(name == "EBPerturb" || name == "EBPerturbGaussian" || name == "EBConstant") {
00064 
00065     bool perturb_values = false;
00066 
00067     Teuchos::Array<double> defaultData(neq);
00068     Teuchos::Array<double> perturb_mag;
00069 
00070     // Only perturb if the user has told us by how much to perturb
00071     if(name != "EBConstant" && icParams.isParameter("Perturb IC")) {
00072 
00073       perturb_values = true;
00074 
00075       perturb_mag = icParams.get("Perturb IC", defaultData);
00076 
00077     }
00078 
00079     /* The element block-based IC specification here is currently a hack. It assumes the initial value is constant
00080      * within each element across the element block (or optionally perturbed somewhat element by element). The
00081      * proper way to do this would be to project the element integration point values to the nodes using the basis
00082      * functions and a consistent mass matrix.
00083      *
00084      * The current implementation uses a single integration point per element - this integration point value for this
00085      * element within the element block is specified in the input file (and optionally perturbed). An approximation
00086      * of the load vector is obtained by accumulating the resulting (possibly perturbed) value into the nodes. Then,
00087      * a lumped version of the mass matrix is inverted and used to solve for the approximate nodal point initial
00088      * conditions.
00089      */
00090 
00091     // Use an Epetra_Vector to hold the lumped mass matrix (has entries only on the diagonal). Zero-ed out.
00092 
00093     Epetra_Vector lumpedMM(soln->Map(), true);
00094 
00095     // Make sure soln is zeroed - we are accumulating into it
00096 
00097     for(int i = 0; i < soln->MyLength(); i++)
00098 
00099       (*soln)[i] = 0;
00100 
00101     // Loop over all worksets, elements, all local nodes: compute soln as a function of coord and wsEBName
00102 
00103 
00104     Teuchos::RCP<AAdapt::AnalyticFunction> initFunc;
00105 
00106     for(int ws = 0; ws < wsElNodeEqID.size(); ws++) { // loop over worksets
00107 
00108       Teuchos::Array<double> data = icParams.get(wsEBNames[ws], defaultData);
00109       // Call factory method from library of initial condition functions
00110 
00111       if(perturb_values) {
00112 
00113         if(name == "EBPerturb")
00114 
00115           initFunc = Teuchos::rcp(new AAdapt::ConstantFunctionPerturbed(neq, numDim, ws, data, perturb_mag));
00116 
00117         else // name == EBGaussianPerturb
00118 
00119           initFunc = Teuchos::rcp(new
00120                                   AAdapt::ConstantFunctionGaussianPerturbed(neq, numDim, ws, data, perturb_mag));
00121       }
00122 
00123       else
00124 
00125         initFunc = Teuchos::rcp(new AAdapt::ConstantFunction(neq, numDim, data));
00126 
00127       std::vector<double> X(neq);
00128       std::vector<double> x(neq);
00129 
00130       for(int el = 0; el < wsElNodeEqID[ws].size(); el++) { // loop over elements in workset
00131 
00132         for(int i = 0; i < neq; i++)
00133           X[i] = 0;
00134 
00135         for(int ln = 0; ln < wsElNodeEqID[ws][el].size(); ln++) // loop over node local to the element
00136           for(int i = 0; i < neq; i++)
00137             X[i] += coords[ws][el][ln][i]; // nodal coords
00138 
00139         for(int i = 0; i < neq; i++)
00140           X[i] /= (double)neq;
00141 
00142         initFunc->compute(&x[0], &X[0]);
00143 
00144         for(int ln = 0; ln < wsElNodeEqID[ws][el].size(); ln++) { // loop over node local to the element
00145           Teuchos::ArrayRCP<int> lid = wsElNodeEqID[ws][el][ln]; // local node ids
00146 
00147           for(int i = 0; i < neq; i++) {
00148 
00149             (*soln)[lid[i]] += x[i];
00150             //             (*soln)[lid[i]] += X[i]; // Test with coord values
00151             lumpedMM[lid[i]] += 1.0;
00152 
00153           }
00154 
00155         }
00156       }
00157     }
00158 
00159     //  Apply the inverted lumped mass matrix to get the final nodal projection
00160 
00161     for(int i = 0; i < soln->MyLength(); i++)
00162 
00163       (*soln)[i] /= lumpedMM[i];
00164 
00165     return;
00166 
00167   }
00168 
00169   if(name == "Coordinates") {
00170 
00171     // Place the coordinate locations of the nodes into the solution vector for an initial guess
00172 
00173     int numDOFsPerDim = neq / numDim;
00174 
00175     for(int ws = 0; ws < wsElNodeEqID.size(); ws++) {
00176       for(int el = 0; el < wsElNodeEqID[ws].size(); el++) {
00177         for(int ln = 0; ln < wsElNodeEqID[ws][el].size(); ln++) {
00178 
00179           const double* X = coords[ws][el][ln];
00180           Teuchos::ArrayRCP<int> lid = wsElNodeEqID[ws][el][ln];
00181 
00182 /*
00183 numDim = 3; numDOFSsPerDim = 2 (coord soln, tgt soln)
00184 X[0] = x;
00185 X[1] = y;
00186 X[2] = z;
00187 lid[0] = DOF[0],eq[0] (x eqn)
00188 lid[1] = DOF[0],eq[1] (y eqn)
00189 lid[2] = DOF[0],eq[2] (z eqn)
00190 lid[3] = DOF[1],eq[0] (x eqn)
00191 lid[4] = DOF[1],eq[1] (y eqn)
00192 lid[5] = DOF[1],eq[2] (z eqn)
00193 */
00194 
00195           for(int j = 0; j < numDOFsPerDim; j++)
00196             for(int i = 0; i < numDim; i++)
00197               (*soln)[lid[j * numDim + i]] = X[i];
00198 
00199         }
00200       }
00201     }
00202 
00203   }
00204 
00205   else {
00206 
00207     Teuchos::Array<double> defaultData(neq);
00208     Teuchos::Array<double> data = icParams.get("Function Data", defaultData);
00209 
00210     // Call factory method from library of initial condition functions
00211     Teuchos::RCP<AAdapt::AnalyticFunction> initFunc
00212       = createAnalyticFunction(name, neq, numDim, data);
00213 
00214     // Loop over all worksets, elements, all local nodes: compute soln as a function of coord
00215     std::vector<double> x(neq);
00216 
00217     for(int ws = 0; ws < wsElNodeEqID.size(); ws++) {
00218       for(int el = 0; el < wsElNodeEqID[ws].size(); el++) {
00219         for(int ln = 0; ln < wsElNodeEqID[ws][el].size(); ln++) {
00220           const double* X = coords[ws][el][ln];
00221           Teuchos::ArrayRCP<int> lid = wsElNodeEqID[ws][el][ln];
00222 
00223           for(int i = 0; i < neq; i++) x[i] = (*soln)[lid[i]];
00224 
00225           initFunc->compute(&x[0], X);
00226 
00227           for(int i = 0; i < neq; i++)(*soln)[lid[i]] = x[i];
00228         }
00229       }
00230     }
00231 
00232   }
00233 
00234 }
00235 
00236 }

Generated on Wed Mar 26 2014 18:36:35 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1