v0.15.0
Loading...
Searching...
No Matches
mofem/tutorials/scl-10/initial_diffusion.cpp
/**
* \file inital_diffusion.cpp
* \example mofem/tutorials/scl-10/initial_diffusion.cpp
*
**/
#include <stdlib.h>
#include <cmath>
#include <MoFEM.hpp>
#define BOOST_MATH_GAUSS_NO_COMPUTE_ON_DEMAND
using namespace MoFEM;
static char help[] = "...\n\n";
template <int DIM> struct ElementsAndOps {};
//! [Define dimension]
constexpr int SPACE_DIM = 3; //< Space dimension of problem, mesh
//! [Define dimension]
using DomainEleOp = DomainEle::UserDataOperator;
const double n = 1.44; ///< refractive index of diffusive medium
const double c = 30.; ///< speed of light (cm/ns)
const double v = c / n; ///< phase velocity of light in medium (cm/ns)
double mu_a; ///< absorption coefficient (cm^-1)
double mu_sp; ///< scattering coefficient (cm^-1)
double D;
double beam_radius; //< spot radius
double flux_magnitude = 1e3; ///< impulse magnitude
double initial_time;
char out_file_name[255] = "init_file.dat";;
int numHoLevels = 1;
PetscBool output_volume = PETSC_FALSE;
#include <boost/math/quadrature/gauss_kronrod.hpp>
using namespace boost::math::quadrature;
struct OpError : public DomainEleOp {
OpError(boost::shared_ptr<VectorDouble> u_at_pts_ptr, double &l2_error)
: DomainEleOp("PHOTON_FLUENCE_RATE", OPROW), uAtPtsPtr(u_at_pts_ptr),
l2Error(l2_error) {
// Only will be executed once on vertices
std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
}
private:
boost::shared_ptr<VectorDouble> uAtPtsPtr;
double &l2Error;
};
public:
// Declaration of the main function to run analysis
/**
* @brief Pulse is infinitely short.
*
* \note It is good approximation of pulse in femtosecond scale. To make it
* longer one can apply third integral over time.
*
* \note Note analysis in photon_diffusion is shifted in time by initial_time.
*
* @param x
* @param y
* @param z
* @return double
*/
static double sourceFunction(const double x, const double y, const double z) {
const double A = 4. * D * v * initial_time;
const double T =
(v / pow(M_PI * A, 3. / 2.)) * exp(-mu_a * v * initial_time);
auto phi_pulse = [&](const double r_s, const double phi_s) {
const double xs = r_s * cos(phi_s);
const double ys = r_s * sin(phi_s);
const double xp = x - xs - beam_centre_x;
const double yp = y - ys - beam_centre_y;
const double zp1 = z + slab_thickness / 2. - 1. / mu_sp;
const double zp2 = z + slab_thickness / 2. + 1. / mu_sp;
const double P1 = xp * xp + yp * yp + zp1 * zp1;
const double P2 = xp * xp + yp * yp + zp2 * zp2;
return r_s * (exp(-P1 / A) - exp(-P2 / A));
};
auto f = [&](const double r_s) {
auto g = [&](const double phi_s) { return phi_pulse(r_s, phi_s); };
return gauss_kronrod<double, 15>::integrate(
g, 0, 2 * M_PI, 0, std::numeric_limits<float>::epsilon());
};
return T * flux_magnitude *
gauss_kronrod<double, 15>::integrate(
f, 0, beam_radius, 0, std::numeric_limits<float>::epsilon());
};
private:
// Declaration of other main functions called in runProgram()
// Main interfaces
};
PhotonDiffusion::PhotonDiffusion(MoFEM::Interface &m_field) : mField(m_field) {}
CHKERR simple->getOptions();
CHKERR simple->loadFile();
}
CHKERR simple->addDomainField("PHOTON_FLUENCE_RATE", H1,
CHKERR simple->addBoundaryField("PHOTON_FLUENCE_RATE", H1,
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-flux_magnitude",
&flux_magnitude, PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-slab_thickness",
&slab_thickness, PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-beam_radius", &beam_radius,
PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-beam_centre_x", &beam_centre_x,
PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-beam_centre_y", &beam_centre_y,
PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-mu_a", &mu_a, PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-mu_sp", &mu_sp, PETSC_NULLPTR);
CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-initial_time", &initial_time,
PETSC_NULLPTR);
CHKERR PetscOptionsGetString(PETSC_NULLPTR, "", "-output_file", out_file_name,
255, PETSC_NULLPTR);
CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-output_volume", &output_volume,
PETSC_NULLPTR);
D = 1. / (3. * (mu_a + mu_sp));
MOFEM_LOG("INITIAL", Sev::inform) << "Refractive index: " << n;
MOFEM_LOG("INITIAL", Sev::inform) << "Speed of light (cm/ns): " << c;
MOFEM_LOG("INITIAL", Sev::inform)
<< "Phase velocity in medium (cm/ns): " << v;
MOFEM_LOG("INITIAL", Sev::inform)
<< "Absorption coefficient (cm^-1): " << mu_a;
MOFEM_LOG("INITIAL", Sev::inform)
<< "Scattering coefficient (cm^-1): " << mu_sp;
MOFEM_LOG("INITIAL", Sev::inform) << "Diffusion coefficient D : " << D;
MOFEM_LOG("INITIAL", Sev::inform) << "Impulse magnitude: " << flux_magnitude;
MOFEM_LOG("INITIAL", Sev::inform) << "Compute time (ns): " << initial_time;
MOFEM_LOG("INITIAL", Sev::inform) << "Slab thickness: " << slab_thickness;
int order = 2;
CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
MOFEM_LOG("INITIAL", Sev::inform) << "Approximation order: " << order;
CHKERR simple->setFieldOrder("PHOTON_FLUENCE_RATE", order);
// if (numHoLevels > 0) {
// Range ho_ents;
// for (_IT_CUBITMESHSETS_BY_SET_TYPE_FOR_LOOP_(mField, BLOCKSET, it)) {
// if (it->getName().compare(0, 3, "CAM") == 0) {
// CHKERR mField.get_moab().get_entities_by_dimension(it->getMeshset(), 2,
// ho_ents, true);
// }
// }
// EntityHandle meshset;
// CHKERR mField.get_moab().create_meshset(MESHSET_SET, meshset);
// CHKERR mField.get_moab().add_entities(meshset, ho_ents);
// std::string field_name;
// field_name = "out_test_" +
// boost::lexical_cast<std::string>(mField.get_comm_rank()) +
// ".vtk";
// CHKERR mField.get_moab().write_file(field_name.c_str(), "VTK", "", &meshset,
// 1);
// CHKERR mField.get_moab().delete_entities(&meshset, 1);
// CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(ho_ents);
// CHKERR simple->setFieldOrder("PHOTON_FLUENCE_RATE", order + 1, &ho_ents);
// CHKERR mField.getInterface<CommInterface>()->synchroniseFieldEntities(
// "PHOTON_FLUENCE_RATE");
// }
CHKERR simple->setUp();
}
auto integration_rule = [](int o_row, int o_col, int approx_order) {
return 2 * approx_order;
};
auto *pipeline_mng = mField.getInterface<PipelineManager>();
CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
CHKERR pipeline_mng->setBoundaryLhsIntegrationRule(integration_rule);
CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(integration_rule);
}
}
// Get boundary edges marked in block named "BOUNDARY_CONDITION"
Range boundary_ents;
std::string entity_name = it->getName();
if (entity_name.compare(0, 3, "INT") == 0) {
CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 1,
boundary_ents, true);
}
}
// Add vertices to boundary entities
Range boundary_verts;
CHKERR mField.get_moab().get_connectivity(boundary_ents, boundary_verts,
true);
boundary_ents.merge(boundary_verts);
// Remove DOFs as homogeneous boundary condition is used
CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
simple->getProblemName(), "PHOTON_FLUENCE_RATE", boundary_ents);
}
auto bc_mng = mField.getInterface<BcManager>();
auto &bc_map = bc_mng->getBcMapByBlockName();
auto add_domain_base_ops = [&](auto &pipeline) {
auto jac_ptr = boost::make_shared<MatrixDouble>();
auto det_ptr = boost::make_shared<VectorDouble>();
pipeline.push_back(new OpCalculateHOJacVolume(jac_ptr));
pipeline.push_back(new OpInvertMatrix<3>(jac_ptr, det_ptr, nullptr));
pipeline.push_back(new OpSetHOWeights(det_ptr));
};
auto add_domain_lhs_ops = [&](auto &pipeline) {
pipeline.push_back(new OpDomainMass(
"PHOTON_FLUENCE_RATE", "PHOTON_FLUENCE_RATE",
[](const double, const double, const double) { return 1; }));
};
auto add_domain_rhs_ops = [&](auto &pipeline) {
pipeline.push_back(
new OpDomainSource("PHOTON_FLUENCE_RATE", sourceFunction));
};
auto pipeline_mng = mField.getInterface<PipelineManager>();
add_domain_base_ops(pipeline_mng->getOpDomainLhsPipeline());
add_domain_base_ops(pipeline_mng->getOpDomainRhsPipeline());
add_domain_lhs_ops(pipeline_mng->getOpDomainLhsPipeline());
add_domain_rhs_ops(pipeline_mng->getOpDomainRhsPipeline());
}
auto *pipeline_mng = mField.getInterface<PipelineManager>();
auto solver = pipeline_mng->createKSP();
CHKERR KSPSetFromOptions(solver);
// CHKERR KSPSetUp(solver);
auto dm = simple->getDM();
auto X = createDMVector(dm);
auto F = vectorDuplicate(X);
MOFEM_LOG("INITIAL", Sev::inform) << "Solver start";
CHKERR KSPSolve(solver, F, X);
CHKERR VecGhostUpdateBegin(X, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(X, INSERT_VALUES, SCATTER_FORWARD);
CHKERR DMoFEMMeshToLocalVector(dm, X, INSERT_VALUES, SCATTER_REVERSE);
MOFEM_LOG("INITIAL", Sev::inform)
<< "writing vector in binary to " << out_file_name << " ...";
PetscViewer viewer;
PetscViewerBinaryOpen(PETSC_COMM_WORLD, out_file_name, FILE_MODE_WRITE,
&viewer);
VecView(X, viewer);
PetscViewerDestroy(&viewer);
MOFEM_LOG("INITIAL", Sev::inform) << "Solver done";
}
auto *pipeline_mng = mField.getInterface<PipelineManager>();
pipeline_mng->getDomainLhsFE().reset();
auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
auto u_ptr = boost::make_shared<VectorDouble>();
post_proc_fe->getOpPtrVector().push_back(
new OpCalculateScalarFieldValues("U", u_ptr));
post_proc_fe->getOpPtrVector().push_back(
new OpPPMap(
post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
{{"PHOTON_FLUENCE_RATE", u_ptr}},
{},
{},
{})
);
pipeline_mng->getDomainRhsFE() = post_proc_fe;
CHKERR pipeline_mng->loopFiniteElements();
CHKERR post_proc_fe->writeFile("out_initial.h5m");
}
}
int main(int argc, char *argv[]) {
// Initialisation of MoFEM/PETSc and MOAB data structures
const char param_file[] = "param_file.petsc";
MoFEM::Core::Initialize(&argc, &argv, param_file, help);
// Add logging channel for example
auto core_log = logging::core::get();
core_log->add_sink(
LogManager::createSink(LogManager::getStrmWorld(), "INITIAL"));
LogManager::setLog("INITIAL");
MOFEM_LOG_TAG("INITIAL", "initial_diffusion")
// Error handling
try {
// Register MoFEM discrete manager in PETSc
DMType dm_name = "DMMOFEM";
// Create MOAB instance
moab::Core mb_instance; // mesh database
moab::Interface &moab = mb_instance; // mesh database interface
// Create MoFEM instance
MoFEM::Core core(moab); // finite element database
MoFEM::Interface &m_field = core; // finite element interface
// Run the main analysis
PhotonDiffusion heat_problem(m_field);
CHKERR heat_problem.runProgram();
}
// Finish work: cleaning memory, getting statistics, etc.
return 0;
}
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
static char help[]
int main()
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ BLOCKSET
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
@ F
auto integration_rule
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define _IT_CUBITMESHSETS_BY_SET_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet having a particular BC meshset in a moFEM field.
BcMapByBlockName & getBcMapByBlockName()
Get the boundary condition map.
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< 1, 1, SPACE_DIM > OpDomainGradGrad
Definition helmholtz.cpp:25
double mu_sp
scattering coefficient (cm^-1)
double flux_magnitude
impulse magnitude
char out_file_name[255]
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpDomainTimesScalarField
double beam_centre_y
int numHoLevels
double beam_centre_x
const double c
speed of light (cm/ns)
double slab_thickness
double beam_radius
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, 1, SPACE_DIM > OpDomainGradTimesVec
double initial_time
double D
PetscBool output_volume
double mu_a
absorption coefficient (cm^-1)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
OpCalculateHOJacForVolume OpCalculateHOJacVolume
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
double mu_sp
scattering coefficient (cm^-1)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, 1 > OpDomainMass
double A
const double c
speed of light (cm/ns)
int order
double D
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, 1 > OpDomainSource
PetscBool output_volume
double mu_a
absorption coefficient (cm^-1)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
static constexpr int approx_order
constexpr double g
Boundary condition manager for finite element problem setup.
virtual moab::Interface & get_moab()=0
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:118
Deprecated interface functions.
Specialization for double precision scalar field values calculation.
Operator for inverting matrices at integration points.
Post post-proc data at points from hash maps.
Set integration weights for higher-order elements.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
Problem manager is used to build and partition problems.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
boost::shared_ptr< VectorDouble > uAtPtsPtr
double & l2Error
MoFEMErrorCode assembleSystem()
MoFEMErrorCode solveSystem()
MoFEM::Interface & mField
MoFEMErrorCode readMesh()
MoFEMErrorCode outputResults()
MoFEMErrorCode initialCondition()
PhotonDiffusion(MoFEM::Interface &m_field)
MoFEMErrorCode checkResults()
MoFEMErrorCode runProgram()
MoFEMErrorCode boundaryCondition()
static double sourceFunction(const double x, const double y, const double z)
Pulse is infinitely short.
MoFEMErrorCode setIntegrationRules()
MoFEMErrorCode setupProblem()