3D dynamic adaptive mesh refinement (AMR) using PABLOThis example creates a 3D Octree mesh on the cube domain [0,1]x[0,1]x[0,1]. The domain is adapted to track a set of moving bubbles with random initialization.
#include "bitpit_PABLO.hpp"
#if BITPIT_ENABLE_MPI==1
#include "PABLO_userDataComm.hpp"
#include "PABLO_userDataLB.hpp"
#include <mpi.h>
#endif
using namespace std;
using namespace bitpit;
class bubble{
public:
double c[3];
double r;
};
void run()
{
int iter = 0;
pabloBB.setBalanceCodimension(1);
int idx = 0;
pabloBB.setBalance(idx,true);
for (iter=1; iter<4; iter++){
pabloBB.adaptGlobalRefine();
}
#if BITPIT_ENABLE_MPI==1
pabloBB.loadBalance();
#endif
uint32_t nocts = pabloBB.getNumOctants();
srand(0);
#if BITPIT_ENABLE_MPI==1
int nb = 50;
#else
int nb = 10;
#endif
vector<bubble> BB;
vector<bubble> BB0;
vector<double> DZ;
vector<double> OM;
vector<double> AA;
for (int i=0; i<nb; i++){
double randc[3];
randc[0] = 0.8 * (double) (rand()) / RAND_MAX + 0.1;
randc[1] = 0.8 * (double) (rand()) / RAND_MAX + 0.1;
randc[2] = (double) (rand()) / RAND_MAX - 0.5;
double randr = (0.05 * (double) (rand()) / RAND_MAX + 0.04);
double dz = 0.005 + 0.05 * (double) (rand()) / RAND_MAX;
double omega = 0.5 * (double) (rand()) / RAND_MAX;
double aa = 0.15 * (double) (rand()) / RAND_MAX;
bubble bb;
bb.c[0] = randc[0];
bb.c[1] = randc[1];
bb.c[2] = randc[2];
bb.r = randr;
BB.push_back(bb);
BB0.push_back(bb);
DZ.push_back(dz);
OM.push_back(omega);
AA.push_back(aa);
}
double t0 = 0;
double t = t0;
double Dt = 0.5;
vector<double> oct_data(nocts, 0.0),oct_data_ghost;
vector<double> oct_data_new(nocts, 0.0);
int itstart = 1;
int itend = 200;
for (iter=itstart; iter<itend; iter++){
if(pabloBB.getRank()==0)
cout <<
"iter " << iter << endl;
t += Dt;
for (int i=0; i<nb; i++){
BB[i].c[0] = BB0[i].c[0];
BB[i].c[1] = BB0[i].c[1];
BB[i].c[2] = BB[i].c[2]+ Dt*DZ[i];
}
bool adapt = true;
while (adapt){
for (unsigned int i=0; i<nocts; i++){
bool inside = false;
vector<array<double,3> > nodes = pabloBB.getNodes(i);
array<double,3> center = pabloBB.getCenter(i);
int ib = 0;
while (!inside && ib<nb){
double xc = BB[ib].c[0];
double yc = BB[ib].c[1];
double zc = BB[ib].c[2];
double radius = BB[ib].r;
if (((!inside))){
if (((
pow((center[0]-xc),2.0)+
pow((center[1]-yc),2.0)+
pow((center[2]-zc),2.0) <= 1.25*
pow(radius,2.0) &&
pow((center[0]-xc),2.0)+
pow((center[1]-yc),2.0)+
pow((center[2]-zc),2.0) >= 0.75*
pow(radius,2.0)))){
if (pabloBB.getLevel(i) < 7){
pabloBB.setMarker(i,1);
oct_data[i] = 1.0;
}
else{
pabloBB.setMarker(i,0);
oct_data[i] = 1.0;
}
inside = true;
}
}
for (int j=0; j<8; j++){
double x = nodes[j][0];
double y = nodes[j][1];
double z = nodes[j][2];
if (((!inside))){
if (((
pow((x-xc),2.0)+
pow((y-yc),2.0)+
pow((z-zc),2.0) <= 1.25*
pow(radius,2.0) &&
pow((x-xc),2.0)+
pow((y-yc),2.0)+
pow((z-zc),2.0) >= 0.75*
pow(radius,2.0)))){
if (pabloBB.getLevel(i) < 7){
pabloBB.setMarker(i,1);
oct_data[i] = 1.0;
}
else{
pabloBB.setMarker(i,0);
oct_data[i] = 1.0;
}
inside = true;
}
}
}
ib++;
}
if (!inside){
oct_data[i] = 0.0;
if (pabloBB.getLevel(i) > 3){
pabloBB.setMarker(i,3-pabloBB.getLevel(i));
}
}
}
vector<uint32_t> mapidx;
vector<bool> isghost;
adapt = pabloBB.adapt(true);
nocts = pabloBB.getNumOctants();
oct_data_new.resize(nocts, 0);
for (uint32_t i=0; i<nocts; i++){
pabloBB.getMapping(i, mapidx, isghost);
oct_data_new[i] = oct_data[mapidx[0]];
}
oct_data = oct_data_new;
vector<double>().swap(oct_data_new);
}
#if BITPIT_ENABLE_MPI==1
UserDataLB<vector<double> > data_lb(oct_data,oct_data_ghost);
pabloBB.loadBalance(data_lb);
nocts = pabloBB.getNumOctants();
#endif
pabloBB.updateConnectivity();
pabloBB.writeTest("PabloBubble3D_iter"+to_string(static_cast<unsigned long long>(iter)), oct_data);
}
}
int main(int argc, char *argv[])
{
#if BITPIT_ENABLE_MPI==1
MPI_Init(&argc,&argv);
#else
#endif
int nProcs;
int rank;
#if BITPIT_ENABLE_MPI==1
MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
#else
nProcs = 1;
rank = 0;
#endif
log::manager().initialize(log::MODE_SEPARATE, false, nProcs, rank);
log::cout() << log::fileVerbosity(log::LEVEL_INFO);
log::cout() << log::disableConsole();
try {
run();
} catch (const std::exception &exception) {
log::cout() << exception.what();
exit(1);
}
#if BITPIT_ENABLE_MPI==1
MPI_Finalize();
#endif
}
std::array< T, d > pow(std::array< T, d > &x, double p)
#define BITPIT_UNUSED(variable)
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)