Line data Source code
1 : /**********************************************************************/ 2 : /* DO NOT MODIFY THIS HEADER */ 3 : /* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */ 4 : /* */ 5 : /* Copyright 2017 Battelle Energy Alliance, LLC */ 6 : /* ALL RIGHTS RESERVED */ 7 : /**********************************************************************/ 8 : 9 : #include "MyTRIMDiracRun.h" 10 : #include "MooseMesh.h" 11 : 12 : // libmesh includes 13 : #include "libmesh/quadrature.h" 14 : #include "libmesh/parallel_algebra.h" 15 : 16 : #include <queue> 17 : 18 : registerMooseObject("MagpieApp", MyTRIMDiracRun); 19 : 20 : InputParameters 21 38 : MyTRIMDiracRun::validParams() 22 : { 23 38 : InputParameters params = MyTRIMRunBase::validParams(); 24 38 : params.addClassDescription("Run a TRIM binary collision Monte Carlo simulation across the entire " 25 : "sample and gather the results for use with a source DiracKernel."); 26 38 : return params; 27 0 : } 28 : 29 19 : MyTRIMDiracRun::MyTRIMDiracRun(const InputParameters & parameters) 30 : : MyTRIMRunBase(parameters), 31 19 : _perf_trim(registerTimedSection("trim", 2)), 32 38 : _perf_finalize(registerTimedSection("finalize", 2)) 33 : { 34 19 : if (_trim_parameters.desired_npka != 0) 35 0 : mooseError("Result scaling not supported in MyTRIMDiracRun"); 36 19 : } 37 : 38 : void 39 19 : MyTRIMDiracRun::execute() 40 : { 41 19 : _result_list.clear(); 42 : 43 : // bail out early if no run is requested for this timestep 44 19 : if (!_rasterizer.executeThisTimestep()) 45 0 : return; 46 : 47 : // trigger the creation of a master PointLocator outside the threaded region 48 19 : _mesh.getPointLocator(); 49 : 50 : // build thread loop functor 51 19 : ThreadedRecoilDiracSourceLoop rl(_rasterizer, _mesh); 52 : 53 : // output the number of recoils being launched 54 19 : _console << "\nMyTRIM: Running " << _trim_parameters.original_npka << " recoils." << std::endl; 55 : 56 : // run threads 57 : { 58 19 : TIME_SECTION(_perf_trim); 59 38 : Threads::parallel_reduce(PKARange(_pka_list.begin(), _pka_list.end()), rl); 60 : } 61 : 62 : // fetch the joined data from thread 0 63 19 : _result_list = rl.getResultList(); 64 19 : } 65 : 66 : void 67 19 : MyTRIMDiracRun::finalize() 68 : { 69 19 : TIME_SECTION(_perf_finalize); 70 : 71 19 : if (!_rasterizer.executeThisTimestep()) 72 : return; 73 : 74 : // for single processor runs we do not need to do anything here 75 19 : if (_app.n_processors() == 1) 76 : return; 77 : 78 : // create send buffer 79 : std::string send_buffer; 80 : 81 : // create byte buffers for the streams received from all processors 82 : std::vector<std::string> recv_buffers; 83 : 84 : // pack the complex datastructures into the string stream 85 8 : serialize(send_buffer); 86 : 87 : // broadcast serialized data to and receive from all processors 88 8 : _communicator.allgather(send_buffer, recv_buffers); 89 : 90 : // unpack the received data and merge it into the local data structures 91 8 : deserialize(recv_buffers); 92 8 : } 93 : 94 : const MyTRIMDiracRun::MyTRIMResultList & 95 68 : MyTRIMDiracRun::result() const 96 : { 97 68 : return _result_list; 98 : } 99 : 100 : void 101 8 : MyTRIMDiracRun::serialize(std::string & serialized_buffer) 102 : { 103 : // stream for serializing the _result_map structure to a byte stream 104 8 : std::ostringstream oss; 105 8 : dataStore(oss, _result_list, this); 106 : 107 : // Populate the passed in string pointer with the string stream's buffer contents 108 8 : serialized_buffer.assign(oss.str()); 109 8 : } 110 : 111 : void 112 8 : MyTRIMDiracRun::deserialize(std::vector<std::string> & serialized_buffers) 113 : { 114 : mooseAssert(serialized_buffers.size() == _app.n_processors(), 115 : "Unexpected size of serialized_buffers: " << serialized_buffers.size()); 116 : 117 : // The input string stream used for deserialization 118 8 : std::istringstream iss; 119 : 120 : // Loop over all datastructures for all procerssors to perfrom the gather operation 121 24 : for (unsigned int rank = 0; rank < serialized_buffers.size(); ++rank) 122 : { 123 : // skip the current processor (its data is already in the structures) 124 16 : if (rank == processor_id()) 125 8 : continue; 126 : 127 : // populate the stream with a new buffer and reset stream state 128 : iss.str(serialized_buffers[rank]); 129 8 : iss.clear(); 130 : 131 : // Load the communicated data into temporary structures 132 : MyTRIMResultList other_result_list; 133 8 : dataLoad(iss, other_result_list, this); 134 : 135 8 : _result_list.insert(_result_list.end(), other_result_list.begin(), other_result_list.end()); 136 : } 137 8 : }