Skip to content

Commit

Permalink
Can reset an App at a specific time closes #1970
Browse files Browse the repository at this point in the history
r18983
  • Loading branch information
friedmud authored and permcody committed Feb 14, 2014
1 parent 7eff9f8 commit 37a0cc6
Show file tree
Hide file tree
Showing 16 changed files with 510 additions and 71 deletions.
5 changes: 5 additions & 0 deletions framework/include/executioners/Transient.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ class Transient: public Executioner
*/
virtual void setTime(Real t) { _time = t; };

/**
* Set the old time.
*/
virtual void setTimeOld(Real t){ _time_old = t; };

/**
* Forces the problem to output right now.
*/
Expand Down
34 changes: 34 additions & 0 deletions framework/include/multiapps/MultiApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class MultiApp : public MooseObject

virtual ~MultiApp();

/**
* Gets called just before transfers are done _to_ the MultiApp
* (Which is just before the MultiApp is solved)
*/
virtual void preTransfer(Real dt, Real target_time);

/**
* Re-solve all of the Apps.
*/
Expand Down Expand Up @@ -137,6 +143,18 @@ class MultiApp : public MooseObject
*/
Point position(unsigned int app) { return _positions[app]; }

/**
* "Reset" the App corresponding to the global App number
* passed in. "Reset" means that the App will be deleted
* and recreated. The time for the new App will be set
* to the current simulation time. This might be handy
* if some sub-app in your simulation needs to get replaced
* by a "new" piece of material.
*
* @param global_app The global app number to reset.
*/
virtual void resetApp(unsigned int global_app);

/**
* Get the MPI communicator this MultiApp is operating on.
* @return The MPI comm for this MultiApp
Expand All @@ -150,6 +168,13 @@ class MultiApp : public MooseObject
bool isRootProcessor() { return _my_rank == 0; }

protected:
/**
* Helper function for creating an App instance.
*
* @param i The local app number to create.
*/
void createApp(unsigned int i, unsigned int output_sequence = 0);

/**
* Create an MPI communicator suitable for each app.
*
Expand Down Expand Up @@ -223,6 +248,15 @@ class MultiApp : public MooseObject
/// Whether or not to move the output of the MultiApp into position
bool _output_in_position;

/// The time at which to reset apps
Real _reset_time;

/// The apps to be reset
std::vector<unsigned int> _reset_apps;

/// Whether or not apps have been reset
bool _reset_happened;

/// Whether or not this processor as an App _at all_
bool _has_an_app;
};
Expand Down
21 changes: 21 additions & 0 deletions framework/include/multiapps/TransientMultiApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,28 @@ class TransientMultiApp :
*/
Real computeDT();

/**
* "Reset" the App corresponding to the global App number
* passed in. "Reset" means that the App will be deleted
* and recreated. The time for the new App will be set
* to the current simulation time. This might be handy
* if some sub-app in your simulation needs to get replaced
* by a "new" piece of material.
*
* @param global_app The global app number to reset.
*/
virtual void resetApp(unsigned int global_app);

private:
/**
* Setup the executioner for the local app.
*
* @param i The local app number for the app that needs to be setup.
* @param time The time to set as the current time for the App
* @param output_initial Whether or not the app should be allowed to output its initial condition
*/
void setupApp(unsigned int i, Real time = 0.0, bool output_initial = true);

std::vector<Transient *> _transient_executioners;

bool _sub_cycling;
Expand Down
8 changes: 6 additions & 2 deletions framework/src/base/FEProblem.C
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,12 @@ FEProblem::getMultiApp(const std::string & multi_app_name)
void
FEProblem::execMultiApps(ExecFlagType type)
{
std::vector<MultiApp *> multi_apps = _multi_apps(type)[0].all();

// Do anything that needs to be done to Apps before transfers
for(unsigned int i=0; i<multi_apps.size(); i++)
multi_apps[i]->preTransfer(_dt, _time);

// Execute Transfers _to_ MultiApps
{
std::vector<Transfer *> transfers = _to_multi_app_transfers(type)[0].all();
Expand All @@ -2345,8 +2351,6 @@ FEProblem::execMultiApps(ExecFlagType type)
transfers[i]->execute();
}

std::vector<MultiApp *> multi_apps = _multi_apps(type)[0].all();

if(multi_apps.size())
{
std::cout<<"--Executing MultiApps--"<<std::endl;
Expand Down
120 changes: 81 additions & 39 deletions framework/src/multiapps/MultiApp.C
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ InputParameters validParams<MultiApp>()

params.addParam<bool>("output_in_position", false, "If true this will cause the output from the MultiApp to be 'moved' by its position vector");

params.addParam<Real>("reset_time", std::numeric_limits<Real>::max(), "The time at which to reset Apps given by the 'reset_apps' parameter. Reseting an App means that it is destroyed and recreated, possibly modeling the insertion of 'new' material for that app.");

params.addParam<std::vector<unsigned int> >("reset_apps", "The Apps that will be reset when 'reset_time' is hit. These are the App 'numbers' starting with 0 corresponding to the order of the App positions. Reseting an App means that it is destroyed and recreated, possibly modeling the insertion of 'new' material for that app.");

params.addPrivateParam<std::string>("built_by_action", "add_multi_app");

return params;
Expand All @@ -88,6 +92,9 @@ MultiApp::MultiApp(const std::string & name, InputParameters parameters):
_inflation(getParam<Real>("bounding_box_inflation")),
_max_procs_per_app(getParam<unsigned int>("max_procs_per_app")),
_output_in_position(getParam<bool>("output_in_position")),
_reset_time(getParam<Real>("reset_time")),
_reset_apps(getParam<std::vector<unsigned int> >("reset_apps")),
_reset_happened(false),
_has_an_app(true)
{
if(isParamValid("positions"))
Expand Down Expand Up @@ -136,46 +143,8 @@ MultiApp::MultiApp(const std::string & name, InputParameters parameters):

_apps.resize(_my_num_apps);

Point parent_position = _app.getOutputPosition();

for(unsigned int i=0; i<_my_num_apps; i++)
{
InputParameters app_params = AppFactory::instance().getValidParams(_app_type);
MooseApp * app = AppFactory::instance().create(_app_type, "multi_app", app_params);

std::ostringstream output_base;

// Create an output base by taking the output base of the master problem and appending
// the name of the multiapp + a number to it
if(_fe_problem)
output_base << _fe_problem->out().fileBase() << "_" ;

output_base << _name
<< std::setw(std::ceil(std::log10(_total_num_apps)))
<< std::setprecision(0)
<< std::setfill('0')
<< std::right
<< _first_local_app + i;

_apps[i] = app;

std::string input_file = "";
if(_input_files.size() == 1) // If only one input file was provide, use it for all the solves
input_file = _input_files[0];
else
input_file = _input_files[_first_local_app+i];

app->setInputFileName(input_file);
app->setOutputFileBase(output_base.str());

if(getParam<bool>("output_in_position"))
{
app->setOutputPosition(parent_position + _positions[_first_local_app + i]);
}

app->setupOptions();
app->runInputFile();
}
createApp(i);

// Swap back
Moose::swapLibMeshComm(swapped);
Expand All @@ -194,6 +163,18 @@ MultiApp::~MultiApp()
}
}

void
MultiApp::preTransfer(Real dt, Real target_time)
{
// First, see if any Apps need to be Reset
if(!_reset_happened && target_time + 1e-14 >= _reset_time)
{
_reset_happened = true;
for(unsigned int i=0; i<_reset_apps.size(); i++)
resetApp(_reset_apps[i]);
}
}

Executioner *
MultiApp::getExecutioner(unsigned int app)
{
Expand Down Expand Up @@ -299,6 +280,67 @@ MultiApp::hasLocalApp(unsigned int global_app)
return false;
}

void
MultiApp::resetApp(unsigned int global_app)
{
MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

if(hasLocalApp(global_app))
{
unsigned int local_app = globalAppToLocal(global_app);
delete _apps[local_app];
createApp(local_app, 1); // The 1 is for the output file name
}

// Swap back
Moose::swapLibMeshComm(swapped);
}

void
MultiApp::createApp(unsigned int i, unsigned int output_sequence)
{
InputParameters app_params = AppFactory::instance().getValidParams(_app_type);
MooseApp * app = AppFactory::instance().create(_app_type, "multi_app", app_params);

std::ostringstream output_base;

// Create an output base by taking the output base of the master problem and appending
// the name of the multiapp + a number to it
if(_fe_problem)
output_base << _fe_problem->out().fileBase() << "_" ;

output_base << _name
<< std::setw(std::ceil(std::log10(_total_num_apps)))
<< std::setprecision(0)
<< std::setfill('0')
<< std::right
<< _first_local_app + i;

if(output_sequence)
output_base << "_" << output_sequence;

_apps[i] = app;

std::string input_file = "";
if(_input_files.size() == 1) // If only one input file was provided, use it for all the solves
input_file = _input_files[0];
else
input_file = _input_files[_first_local_app+i];

app->setInputFileName(input_file);
app->setOutputFileBase(output_base.str());

if(getParam<bool>("output_in_position"))
{
Point parent_position = _app.getOutputPosition();
app->setOutputPosition(parent_position + _positions[_first_local_app + i]);
}

app->setupOptions();
app->runInputFile();
}


void
MultiApp::buildComm()
{
Expand Down
91 changes: 61 additions & 30 deletions framework/src/multiapps/TransientMultiApp.C
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,7 @@ TransientMultiApp::TransientMultiApp(const std::string & name, InputParameters p
_transient_executioners.resize(_my_num_apps);
// Grab Transient Executioners from each app
for(unsigned int i=0; i<_my_num_apps; i++)
{
MooseApp * app = _apps[i];
Transient * ex = dynamic_cast<Transient *>(app->getExecutioner());
if(!ex)
mooseError("MultiApp " << name << " is not using a Transient Executioner!");

ex->init();

FEProblem * problem = appProblem(_first_local_app + i);

if(_interpolate_transfers)
{
AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
System & libmesh_aux_system = aux_system.system();

// We'll store a copy of the auxiliary system's solution at the old time in here
libmesh_aux_system.add_vector("transfer_old", false);

// This will be where we'll transfer the value to for the "target" time
libmesh_aux_system.add_vector("transfer", false);
}

problem->initialSetup();
ex->preExecute();
problem->copyOldSolutions();
_transient_executioners[i] = ex;

if(_detect_steady_state || _tolerate_failure)
ex->allowOutput(false);
}
setupApp(i);
}

// Swap back
Expand Down Expand Up @@ -385,3 +356,63 @@ TransientMultiApp::computeDT()
return smallest_dt;
}

void
TransientMultiApp::resetApp(unsigned int global_app)
{
if(hasLocalApp(global_app))
{
unsigned int local_app = globalAppToLocal(global_app);

// Grab the current time the App is at so we can start the new one at the same place
Real time = _transient_executioners[local_app]->getTime();

MultiApp::resetApp(global_app);

MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

setupApp(local_app, time, false);

// Swap back
Moose::swapLibMeshComm(swapped);
}
}

void
TransientMultiApp::setupApp(unsigned int i, Real time, bool output_initial)
{
MooseApp * app = _apps[i];
Transient * ex = dynamic_cast<Transient *>(app->getExecutioner());
if(!ex)
mooseError("MultiApp " << _name << " is not using a Transient Executioner!");

if(!output_initial)
ex->outputInitial(false);

ex->setTime(time);
ex->setTimeOld(time);

ex->init();

FEProblem * problem = appProblem(_first_local_app + i);

if(_interpolate_transfers)
{
AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
System & libmesh_aux_system = aux_system.system();

// We'll store a copy of the auxiliary system's solution at the old time in here
libmesh_aux_system.add_vector("transfer_old", false);

// This will be where we'll transfer the value to for the "target" time
libmesh_aux_system.add_vector("transfer", false);
}

problem->initialSetup();
ex->preExecute();
problem->copyOldSolutions();
_transient_executioners[i] = ex;

if(_detect_steady_state || _tolerate_failure)
ex->allowOutput(false);
}

Binary file not shown.

0 comments on commit 37a0cc6

Please sign in to comment.