-
Notifications
You must be signed in to change notification settings - Fork 238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Impl. of BalanceProcess #1429
Impl. of BalanceProcess #1429
Conversation
Jenkins: OGS-6/Linux-PRs-dynamic failed: https://svn.ufz.de:8443/job/OGS-6/job/Linux-PRs-dynamic/1178/ |
Jenkins, test this please. |
2 similar comments
Jenkins, test this please. |
Jenkins, test this please. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general it looks good. Only minor things from my side. Thanks for implementing this.
@@ -179,9 +186,11 @@ class Process | |||
unsigned const _integration_order = 2; | |||
GlobalSparsityPattern _sparsity_pattern; | |||
|
|||
protected: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rather move the member up to the existing protected section. ✅
@@ -53,6 +54,12 @@ class LocalAssemblerInterface | |||
NumLib::LocalToGlobalIndexMap const& dof_table, | |||
GlobalVector const& x); | |||
|
|||
virtual std::vector<double> getFlux( | |||
MathLib::Point3d const& p, std::vector<double> const& local_x) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why Point3d? I'd find SpatialPosition more natural. Maybe time has to be passed, too (for time-dependent parameters).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Point3d
is a point given in natural coordinates. I will change the parameter name to better reflect this.- I would implement time depenedency in a separate PR later on when it is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
//! \ogs_file_attr{process__balance__mesh} | ||
balance_config->getConfigParameter<std::string>("mesh"); | ||
balance_pv_name = | ||
//! \ogs_file_attr{process__balance__balance_pv_name} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... balance_property_name ✅
#include "MeshLib/Elements/FaceRule.h" | ||
#include "MeshLib/Elements/Elements.h" | ||
|
||
inline MathLib::Point3d getBulkElementPoint(MeshLib::Quad const& quad, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some docu. ✅
Maybe the defintions should be moved to a cpp file? ✅
typename ShapeMatricesType::ShapeMatrices shape_matrices( | ||
ShapeFunction::DIM, GlobalDim, ShapeFunction::NPOINTS); | ||
|
||
fe.computeShapeFunctions(p.getCoords(), shape_matrices, GlobalDim); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, here you need the Point3D. I guess it has to be in natural coordinates. Maybe that should be documented (and reflected in the argument name).
_integration_method.getNumberOfPoints(); | ||
|
||
std::vector<typename ShapeMatricesType::ShapeMatrices> shape_matrices; | ||
shape_matrices.reserve(n_integration_points); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to store all shape matrices if you only need detJ. ✅
std::size_t const n_integration_points = | ||
_integration_method.getNumberOfPoints(); | ||
// balance[id_of_element] = | ||
// int_{\Gamma_e} \alpha \cdot grad variable \cdot normal \d \Gamma |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
\cdot grad variable
→ \cdot flux
✅
// int_{\Gamma_e} \alpha \cdot grad variable \cdot normal \d \Gamma | ||
for (std::size_t ip(0); ip < n_integration_points; ip++) | ||
{ | ||
pos.setIntegrationPoint(ip); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pos
is currently not used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
component_id < balance.getNumberOfComponents(); | ||
++component_id) | ||
{ | ||
// TODO find solution for 2d case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eigen::Map<...>(bulk_flux.data(), bulk_flux.size()).dot(Eigen::Map<...>(surface_element_normal.data(), surface_element_normal.size())
or similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getSurfaceNormal
returns a MathLib::Vector3
object, i.e., the normal of the surface is always a 3d vector. Maybe we have o handle the 2d bulk / 1d boundary case special, i.e., rotate the 3d normal to the 2d plane. Anyway, I will change this and use the Eigen::Map
solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant the Eigen::Map stuff as a solution for any dimension.
Even though getSurfaceNormal()
returns a 3D vector, in 2D the z-component should always be zero, So you don't need to write a fixed 3
in your implementation.
Shouldn't the following work in any dimension (note the bulk_flux.size()
in both places)?
Eigen::Map<Eigen::RowVectorXd const>(bulk_flux.data(),
bulk_flux.size())
.dot(Eigen::Map<Eigen::RowVectorXd const>(
surface_element_normal.getCoords(), bulk_flux.size())));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The element normal is calculated in the physical space, not in natural coordinates. If the element is not in the x-y-plane then I am not convinced that the z-component of the element normal vanishs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the element is not in the x-y-plane then I am not convinced that the z-component of the element normal vanishs.
But then you are not in 2D (at least for my understanding). OK, there is the case of having 2D elements in 3D space... Let's leave it for later.
pos.setElementID(element_id); | ||
|
||
auto surface_element_normal = | ||
MeshLib::FaceRule::getSurfaceNormal(&_surface_element); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: A different approach is needed for higher order elements. Maybe add a TODO note?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The higher order elements are geometrically linear. Could you explain a little more, what should be different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The higher order elements are geometrically linear.
AFAIK that is not true in general. The higher-order nodes are not necessarily on the faces, but can deviate from them. I think, @nagelt can explain that better than I.
Maybe cf. Isoparametric finite elements: Coordinates have the same shape functions as fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the current implementation only geometricaly linear element are allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to blame the current implementation, but maybe add a comment somewhere that for higher-order elements further work is needed. (E.g., add a todo note at this line.)
381fe63
to
9463d5d
Compare
@@ -191,4 +191,24 @@ std::ostream& operator<<(std::ostream& os, LocalToGlobalIndexMap const& map) | |||
} | |||
#endif // NDEBUG | |||
|
|||
NumLib::LocalToGlobalIndexMap::RowColumnIndices getRowColumnIndices( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There already is a very similar method (getIndices()
) in NumLib/DOF/DOFTableUtil.cpp
Your getVectorValues()
is already provided by EigenVector::get()
etc.
As far as I can see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out, the changes concerning dof table are moved to a separat PR #1442.
I am reworking the implementation. |
b5bb3b7
to
9123797
Compare
I hope I fixed/commented all of @chleh remarks. The review can go on ... |
Two new comments (see above)
afterwards 👍 |
9123797
to
b5affd8
Compare
#ifndef PROCESS_LIB_BALANCEPROCESS_H_ | ||
#define PROCESS_LIB_BALANCEPROCESS_H_ | ||
|
||
#include "NumLib/Extrapolation/LocalLinearLeastSquaresExtrapolator.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not used here ✅
boost::optional<MeshLib::PropertyVector<std::size_t> const&> | ||
bulk_element_ids(boundary_mesh.getProperties() | ||
.template getPropertyVector<std::size_t>( | ||
"OriginalSubsurfaceElementIDs")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think Subsurface is too specific. why not OriginalElementID?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I change the name here, I have to change also the name in the tool ExtractSurface. If you really want change the name I would do this in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to make the name general, but it's not urgent issue. One can change it later when they need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened #1449.
case 3: | ||
return MathLib::Point3d{std::array<double, 3>{{0.0, 1.0 - wp[0], 0.0}}}; | ||
default: | ||
OGS_FATAL("Invalid face id '%u' for the quad."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
argument is missing ✅
|
||
#include "MeshLib/Elements/FaceRule.h" | ||
#include "MeshLib/Elements/Elements.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would add namespace ProcessLib ✅
GlobalDim); | ||
std::vector<double> gradient; | ||
gradient.resize(3); | ||
Eigen::Map<Eigen::RowVectorXd>(gradient.data(), gradient.size()) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is Conductivity not included?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until know for the simple tests conductivity was always 1. I'll add conductivity to the formula.
{ | ||
std::vector<double> init_values( | ||
_balance_mesh->getNumberOfElements(), 0.0); | ||
MeshLib::addPropertyToMesh(*_balance_mesh, _balance_pv_name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it add a new property every time step?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I assume that postTimeStepConcreteProcess()
is called only once. If it is called for every time step a new name for PropertyVector has to be generated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it because GroundwaterFlowProcess solves only one time step? I though postTimeStepConcreteProcess()
is called for every time step...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously it has to be configurable at which timesteps the surface fluxes will be computed.
I suggest to implement it in a follow-up PR, and to leave the current implementation as it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, here I assumed that GroundwaterFlowProcess solves only one time step.
@@ -175,13 +182,13 @@ class Process | |||
|
|||
VectorMatrixAssembler _global_assembler; | |||
|
|||
/// Variables used by this process. | |||
std::vector<std::reference_wrapper<ProcessVariable>> _process_variables; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't it possible to use getProcessVariables()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is possible. I revert my change and use getProcessVariables()
.
auto const k = _process_data.hydraulic_conductivity(t, pos)[0]; | ||
|
||
Eigen::Map<Eigen::RowVectorXd>(flux.data(), flux.size()) = | ||
k * shape_matrices.dNdx * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need a negative sign here, q = - K * grad(head) ✅
21730ac
to
8743fbe
Compare
👍 from my side |
Thanks for the review. Will start rebase and renaming ... |
89cc34e
to
d3f9068
Compare
Allow modification of the component of the specified tuple.
Necessary for BalanceProcess.
d3f9068
to
fe5bcc8
Compare
fe5bcc8
to
ce23b85
Compare
OpenGeoSys development has been moved to GitLab. |
This PR implements the basic infrastructure for balancing fluxes. In the moment the balance can only be calculated for a quad mesh that is a boundary of a hexahedra mesh. This will be extended in further PR. At the moment the balance is only implemented into the GroundwaterFlow but is ready to use in any other process, too. This will also changed in further PRs.
Update
BalanceProcess
toCalculateSurfaceFlux
as suggested by @wenqing and @norihiro-w.