NimbleSM
NimbleSM is a solid mechanics simulation code for dynamic systems
Loading...
Searching...
No Matches
nimble::UqModel Class Reference

#include <nimble_uq.h>

Public Member Functions

 UqModel (int ndim, const GenesisMesh *mesh, ModelData *data)
 
virtual ~UqModel ()=default
 
void ParseConfiguration (std::string const &line)
 
void ParseBlockInput (std::string const &line, const int &block_id, std::string const &nominal_params_string, const std::shared_ptr< nimble::MaterialFactoryBase > &material_factory, bool block_id_present, std::map< int, std::shared_ptr< nimble::Block > > &blocks)
 
void Initialize ()
 
void Finalize ()
 
void Allocate ()
 
void Setup ()
 
void ApplyClosure ()
 
void ReadSamples ()
 
void ScaleParameters ()
 
void WriteSamples ()
 
void PerformAnalyses (const double *reference_coordinates, int num_elem, const int *elem_conn, int block_id, std::shared_ptr< nimble::Block > &block)
 
void Write (double time)
 
int GetNumSamples () const
 
int GetNumParameters () const
 
int GetNumExactSamples () const
 
bool Initialized () const
 
std::vector< double * > & Displacements ()
 
std::vector< double * > & Velocities ()
 
std::vector< double * > & Forces ()
 
std::map< std::string, double > Parameters (int block_id, int sample_i)
 

Constructor & Destructor Documentation

◆ UqModel()

nimble::UqModel::UqModel ( int ndim,
const GenesisMesh * mesh,
ModelData * data )
75 : ndims_(ndims),
76 nnodes_(mesh->GetNumNodes()),
77 nblocks_(mesh->GetNumBlocks()),
78 nsamples_(0),
79 nparameters_(0),
80 mesh_(mesh),
81 data_(data),
82 nexact_samples_(0)
83{
84 nunknowns_ = ndims_ * nnodes_;
85 parameter_samples_.clear();
86 interpolation_coefficients_.clear();
87 initialized_ = false;
88}

◆ ~UqModel()

virtual nimble::UqModel::~UqModel ( )
virtualdefault

Member Function Documentation

◆ Allocate()

void nimble::UqModel::Allocate ( )
283{
284 nominal_force_ = data_->GetVectorNodeData("internal_force").data();
285 std::string prefix = "exact";
286 for (int i = 0; i < nexact_samples_; i++) {
287 std::string tag = std::to_string(i+1);
288 data_->AllocateNodeData(nimble::VECTOR, prefix+"_displacement_" + tag, nnodes_);
289 data_->AllocateNodeData(nimble::VECTOR, prefix+"_velocity_" + tag, nnodes_);
290 data_->AllocateNodeData(nimble::VECTOR, prefix+"_force_" + tag, nnodes_);
291 }
292 prefix = "sample";
293 for (int i = 0; i < napprox_samples_; i++) {
294 std::string tag = std::to_string(i+1);
295 data_->AllocateNodeData(nimble::VECTOR, prefix+"_displacement_" + tag, nnodes_);
296 data_->AllocateNodeData(nimble::VECTOR, prefix+"_velocity_" + tag, nnodes_);
297 data_->AllocateNodeData(nimble::VECTOR, prefix+"_force_" + tag, nnodes_);
298 }
299//std::cout << " DONE Allocate\n" << std::flush;
300}
@ VECTOR
Definition nimble_data_utils.h:89

◆ ApplyClosure()

void nimble::UqModel::ApplyClosure ( )
329{
330 if (!initialized_) { return; }
331 // Now loop over the approximate samples, and apply the interpolation
332 for (int s = 0; s < napprox_samples_; s++) {
333 double* f = forces_[s + nexact_samples_]; // approx after exact
334 // Loop over each node
335 for (int i = 0; i < nunknowns_; ++i) {
336 f[i] = nominal_force_[i] * interpolation_coefficients_[s][0];
337 for (int k = 0; k < nexact_samples_; k++) {
338 double* f_exact = forces_[k];
339 f[i] += f_exact[i] * interpolation_coefficients_[s][k + 1];
340 }
341//std::cout << s << " | " << i << ", " << nominal_force_[i] << " / " << f[i] << "\n";
342 }
343 }
344//std::cout << " DONE ApplyClosure\n" << std::flush;
345}

◆ Displacements()

std::vector< double * > & nimble::UqModel::Displacements ( )
inline
138 {
139 return displacements_;
140 }

◆ Finalize()

void nimble::UqModel::Finalize ( )

◆ Forces()

std::vector< double * > & nimble::UqModel::Forces ( )
inline
148 {
149 return forces_;
150 }

◆ GetNumExactSamples()

int nimble::UqModel::GetNumExactSamples ( ) const
inline
128 {
129 return nexact_samples_;
130 }

◆ GetNumParameters()

int nimble::UqModel::GetNumParameters ( ) const
inline
123 {
124 return parameter_order_.size();
125 }

◆ GetNumSamples()

int nimble::UqModel::GetNumSamples ( ) const
inline
118 {
119 return nsamples_;
120 }

◆ Initialize()

void nimble::UqModel::Initialize ( )
272{
273 ReadSamples();
275 WriteSamples();
276 Allocate();
277 initialized_ = true;
278//std::cout << " DONE Initialize\n" << std::flush;
279}
void WriteSamples()
Definition nimble_uq.cc:247
void ScaleParameters()
Definition nimble_uq.cc:221
void ReadSamples()
Definition nimble_uq.cc:146
void Allocate()
Definition nimble_uq.cc:282

◆ Initialized()

bool nimble::UqModel::Initialized ( ) const
inline
133 {
134 return initialized_;
135 }

◆ Parameters()

std::map< std::string, double > nimble::UqModel::Parameters ( int block_id,
int sample_i )
inline
153 {
154 return parameters_[block_id][sample_i];
155 }

◆ ParseBlockInput()

void nimble::UqModel::ParseBlockInput ( std::string const & line,
const int & block_id,
std::string const & nominal_params_string,
const std::shared_ptr< nimble::MaterialFactoryBase > & material_factory,
bool block_id_present,
std::map< int, std::shared_ptr< nimble::Block > > & blocks )
118{
119//std::cout << " START ParseBlockInput\n" << std::flush;
120 if (line == "none")
121 throw std::invalid_argument( "\nError: NIMBLE_DO_UQ is defined but no uq parameters are specified for material corresponding to block id " + std::to_string(block_id) + "\n");
122 int start_idx = GetNumParameters(); // number of parameter from previous blocks
123 // collect ranges of the uncertain parameters
124 std::list<std::string> items = split(line);
125 while (items.size() > 0) {
126 std::string pname = items.front();
127 items.pop_front();
128 double range = std::stod(items.front());
129 items.pop_front();
130 parameter_uncertainties_[block_id][pname] = range;
131 std::pair <int,std::string> p(block_id,pname);
132 parameter_order_.push_back(p);
133 nparameters_++;
134 }
135
136 // get nominal parameters
137 std::map<std::string, double> parameters = material_factory->parse_material_params_string(nominal_params_string);
138 nominal_parameters_[block_id] = parameters;
139//std::cout << " K " << parameters["bulk_modulus"];
140//std::cout << " G " << parameters["shear_modulus"];
141
142//std::cout << " FINISH ParseBlockInput\n" << std::flush;
143}
int GetNumParameters() const
Definition nimble_uq.h:122
std::list< std::string > split(std::string line)
Definition nimble_uq.cc:64

◆ ParseConfiguration()

void nimble::UqModel::ParseConfiguration ( std::string const & line)
94{
95 std::list<std::string> items = split(line);
96 std::string sampling = items.front();
97 items.pop_front();
98 if (sampling == "file") {
99 samples_file_name_ = items.front();
100 items.pop_front();
101 } else {
102 std::cerr << " !! Error when parsing UQ parameters : !! \n";
103 }
104}

◆ PerformAnalyses()

void nimble::UqModel::PerformAnalyses ( const double * reference_coordinates,
int num_elem,
const int * elem_conn,
int block_id,
std::shared_ptr< nimble::Block > & block )
inline
110 {};

◆ ReadSamples()

void nimble::UqModel::ReadSamples ( )
147{
148 std::ifstream f(samples_file_name_);
149 std::string line;
150 std::list<std::string> items;
151
152 // read 1st line
153 int linenumber = 0;
154 getline(f, line); linenumber++;
155 items.clear();
156 items = split(line);
157 nexact_samples_ = std::stoi(items.front()); // in addition to the nominal
158 items.pop_front();
159 napprox_samples_ = std::stoi(items.front());
160 items.pop_front();
161 nsamples_ = napprox_samples_ + nexact_samples_;
162
163 parameter_samples_.resize(nsamples_);
164 interpolation_coefficients_.resize(napprox_samples_);
165
166 //- (A) -the exact samples (no interp coefficients for these)
167 //--{exact_smpl_1_P1} {exact_smpl_1_P2}
168 //--{exact_smpl_2_P1} {exact_smpl_2_P2}
169 for (int nsmpl = 0; nsmpl < nexact_samples_; nsmpl++) {
170 getline(f, line); linenumber++;
171 items.clear();
172 items = split(line);
173 if (items.size() != nparameters_) {
174 throw std::invalid_argument("\nError: UQ file " + samples_file_name_ + " has not enough exact sample parameters on line " + std::to_string(linenumber) + " expecting " + std::to_string(nparameters_) + " found " + std::to_string(items.size()) + "\n");
175 }
176 for (int n = 0; n < nparameters_; n++) {
177 std::string item = items.front();
178 items.pop_front();
179 parameter_samples_[nsmpl].push_back(std::stod(item)); // exact samples come before the approx samples
180 }
181 }
182//std::cout << " read " << nexact_samples_ << " exact samples\n";
183 //-- (B) the approximate samples, and interpolation coefficients
184 //--{approx_smpl_1_P1} {approx_smpl_1_P2} : {interp_coeff_1} {interp_coeff_2}
185 //--{approx_smpl_2_P1} {approx_smpl_2_P2} : {interp_coeff_1} {interp_coeff_2}
186 int ncoeff = nexact_samples_ + 1; // including nominal
187 for (int nsmpl = 0; nsmpl < napprox_samples_; nsmpl++) {
188 getline(f, line); linenumber++;
189 size_t colon_pos = line.find(":");
190 if (colon_pos == std::string::npos) {
191 throw std::invalid_argument( "\nError: UQ file " + samples_file_name_ + " has wrong format (no colon) on line " + std::to_string(linenumber) + "\n");
192 }
193 std::string params_string = line.substr(0, colon_pos);
194 std::string coeffs_string = line.substr(colon_pos + 1, line.size());
195 items.clear();
196 items = split(params_string);
197 if (items.size() != nparameters_) {
198 throw std::invalid_argument( "\nError: UQ file " + samples_file_name_ + " has " + std::to_string(items.size()) +" parameters (preceding :) on line " + std::to_string(linenumber) + " expecting " + std::to_string(nparameters_) + "\n");
199 }
200 for (int n = 0; n < nparameters_; n++) {
201 std::string item = items.front();
202 items.pop_front();
203 parameter_samples_[nexact_samples_ + nsmpl].push_back(std::stod(item)); // approx samples come after the exact samples
204 }
205 items.clear();
206 items = split(coeffs_string);
207 if (items.size() != ncoeff) {
208 throw std::invalid_argument( "\nError: UQ file " + samples_file_name_ + " has " + std::to_string(items.size()) + " coefficients on line " + std::to_string(linenumber) + " expecting " + std::to_string(ncoeff) + "\n");
209 }
210
211 for (int n = 0; n < ncoeff; n++) {
212 std::string item = items.front();
213 items.pop_front();
214 interpolation_coefficients_[nsmpl].push_back(std::stod(item));
215 }
216 }
217//std::cout << " read " << napprox_samples_ << " approximate samples\n";
218}

◆ ScaleParameters()

void nimble::UqModel::ScaleParameters ( )
222{
223 // initialize sample parameters
224 std::map<int,std::map<std::string, double>>::iterator itr;
225 for (itr = nominal_parameters_.begin() ; itr != nominal_parameters_.end(); itr++ ) {
226 int block_id = itr->first;
227 for (int i = 0 ; i < nsamples_ ; i++) {
228 parameters_[block_id].push_back(itr->second);
229 }
230 }
231 // scale samples with uncertainities to vary uncertain parameters
232 // input file order determines how xis are mapped to physical parameters
233 for (int i = 0 ; i < nparameters_ ; i++) {
234 int block_id = parameter_order_[i].first;
235 std::string name = parameter_order_[i].second;
236 for (int s = 0 ; s < nsamples_ ; s++) {
237 double p0 = parameters_[block_id][s][name];
238 double dpdxi = parameter_uncertainties_[block_id][name];
239 double dxi = parameter_samples_[s][i];
240 double p = p0 + dpdxi*dxi;
241 parameters_[block_id][s][name] = p;
242 }
243 }
244}

◆ Setup()

void nimble::UqModel::Setup ( )
304{
305//std::cout << " START Setup\n" << std::flush;
306 if (!initialized_) { return; }
307 displacements_.clear();
308 velocities_.clear();
309 forces_.clear();
310 std::string prefix = "exact";
311 for (int i = 0; i < nexact_samples_; i++) {
312 std::string tag = std::to_string(i+1);
313 displacements_.push_back( data_->GetNodeData(data_->GetFieldId(prefix+"_displacement_" + tag)));
314 velocities_.push_back( data_->GetNodeData(data_->GetFieldId(prefix+"_velocity_" + tag)));
315 forces_.push_back( data_->GetNodeData(data_->GetFieldId(prefix+"_force_" + tag)));
316 }
317 prefix = "sample";
318 for (int i = 0; i < napprox_samples_; i++) {
319 std::string tag = std::to_string(i+1);
320 displacements_.push_back( data_->GetNodeData(data_->GetFieldId(prefix+"_displacement_" + tag)));
321 velocities_.push_back( data_->GetNodeData(data_->GetFieldId(prefix+"_velocity_" + tag)));
322 forces_.push_back( data_->GetNodeData(data_->GetFieldId(prefix+"_force_" + tag)));
323 }
324//std::cout << " DONE Setup\n" << std::flush;
325}

◆ Velocities()

std::vector< double * > & nimble::UqModel::Velocities ( )
inline
143 {
144 return velocities_;
145 }

◆ Write()

void nimble::UqModel::Write ( double time)
inline
113{};

◆ WriteSamples()

void nimble::UqModel::WriteSamples ( )
248{
249// NOTE/ HACK only do if rank == 0 HOW to get rank id?
250 std::ofstream f("parameter_samples.dat");
251 f << "# ";
252 for (int i = 0 ; i < nparameters_ ; i++) {
253 int block_id = parameter_order_[i].first;
254 std::string name = parameter_order_[i].second;
255 f << name+"_"+std::to_string(block_id) << " ";
256 }
257 f << "\n";
258 for (int s = 0 ; s < nsamples_ ; s++) {
259 for (int i = 0 ; i < nparameters_ ; i++) {
260 int block_id = parameter_order_[i].first;
261 std::string name = parameter_order_[i].second;
262 double p = parameters_[block_id][s][name];
263 f << std::setw(8) << p << " ";
264 }
265 f << "\n";
266 }
267 f.close();
268}

The documentation for this class was generated from the following files: