Skip to content
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

Clang tidy CI test: add several clang-analyzer-* checks to clang tidy CI test #4684

Merged
merged 38 commits into from
Apr 1, 2024

Conversation

lucafedeli88
Copy link
Member

@lucafedeli88 lucafedeli88 commented Feb 9, 2024

This PR adds several clang-analyzer-* checks to clang-tidy CI test:

The following checks are explicitly excluded (osx checks are not relevant for WarpX):

  • clang-analyzer-osx.*
  • clang-analyzer-optin.osx.*

Also this check is excluded, since it generates a non-relevant warning:

Finally, padding check is excluded because it generates warning for lambda functions, which require a verbose NOLINT to be silenced:


Notable changes

Use new AMREX_ASSUME feature to silence warnings

In WarpX we can enforce a given condition by using WARPX_ALWAYS_ASSERT_WITH_MESSAGE . However, the compiler can't see through WARPX_ALWAYS_ASSERT_WITH_MESSAGE and clang-tidy may therefore generate warnings for scenarios that can't actually take place.

A possible solution is to use a newly introduced feature in AMReX: AMREX_ASSUME :

#include <AMReX_Extension.H>
//...
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(m_mf_src != nullptr, "m_mf_src can't be a nullptr.");
AMREX_ASSUME(m_mf_src != nullptr);

After AMREX_ASSUME(m_mf_src != nullptr); most compilers (including gcc, clang, and nvcc) should be able to assume that m_mf_src != nullptr.

Using this feature requires to update the AMReX version.

Change getters of fields and field pointers in WarpX

As discussed with @ax3l (see #4684 (comment)), this PR also changes the getters of the fields and field pointers in the WarpX class:

enum struct FieldType : int
{
    Efield_aux,
    Bfield_aux,
    Efield_fp,
    Bfield_fp,
    current_fp,
    current_fp_nodal,
    rho_fp,
    F_fp,
    G_fp,
    phi_fp,
    vector_potential_fp,
    Efield_cp,
    Bfield_cp,
    current_cp,
    rho_cp,
    F_cp,
    G_cp,
    edge_lengths,
    face_areas,
    Efield_avg_fp,
    Bfield_avg_fp,
    Efield_avg_cp,
    Bfield_avg_cp
};

//...

[[nodiscard]] bool
isFieldInitialized (FieldType field_type, int lev, int direction = 0) const;

[[nodiscard]] amrex::MultiFab*
getFieldPointer (FieldType field_type, int lev, int direction = 0) const;

[[nodiscard]] std::array<const amrex::MultiFab* const, 3>
getFieldPointerArray (FieldType field_type, int lev) const;

const amrex::MultiFab&
getField(FieldType field_type, int lev, int direction = 0) const;

//...
private:

[[nodiscard]] amrex::MultiFab*
getFieldPointerUnchecked (FieldType field_type, int lev, int direction = 0) const;

getFieldPointerUnchecked does not check if the requested pointer is != nullptr . This function is conceived to be used internally by the other getters, which check if the pointer is valid and, in case it isn't, they abort.

@lucafedeli88 lucafedeli88 added component: tests Tests and CI cleaning Clean code, improve readability labels Feb 9, 2024
@lucafedeli88 lucafedeli88 changed the title [WIP] Clang tidy CI test: add several clang-analyzer-* checks to clang tidy CI test Clang tidy CI test: add several clang-analyzer-* checks to clang tidy CI test Feb 9, 2024
@ax3l ax3l self-requested a review February 13, 2024 00:05
@ax3l ax3l self-assigned this Feb 13, 2024
@@ -54,6 +54,12 @@ JFunctor::operator() (amrex::MultiFab& mf_dst, int dcomp, const int /*i_buffer*/
mypc.DepositCurrent(current_fp_temp, warpx.getdt(m_lev), 0.0);
}

InterpolateMFForDiag(mf_dst, *m_mf_src, dcomp, warpx.DistributionMap(m_lev),
m_convertRZmodes2cartesian);
if (m_mf_src != nullptr){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function get_pointer_current_fp should throw instead of having to check the return value in user code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to address this issue, would it be okay to restructure this part of WarpX.H

    [[nodiscard]] amrex::MultiFab * get_pointer_Efield_aux  (int lev, int direction) const { return Efield_aux[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_Bfield_aux  (int lev, int direction) const { return Bfield_aux[lev][direction].get(); }

    [[nodiscard]] amrex::MultiFab * get_pointer_Efield_fp  (int lev, int direction) const { return Efield_fp[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_Bfield_fp  (int lev, int direction) const { return Bfield_fp[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_current_fp  (int lev, int direction) const { return current_fp[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_current_fp_nodal  (int lev, int direction) const { return current_fp_nodal[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_rho_fp  (int lev) const { return rho_fp[lev].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_F_fp  (int lev) const { return F_fp[lev].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_G_fp  (int lev) const { return G_fp[lev].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_phi_fp  (int lev) const { return phi_fp[lev].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_vector_potential_fp  (int lev, int direction) const { return vector_potential_fp_nodal[lev][direction].get(); }

    [[nodiscard]] amrex::MultiFab * get_pointer_Efield_cp  (int lev, int direction) const { return Efield_cp[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_Bfield_cp  (int lev, int direction) const { return Bfield_cp[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_current_cp  (int lev, int direction) const { return current_cp[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_rho_cp  (int lev) const { return rho_cp[lev].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_F_cp  (int lev) const { return F_cp[lev].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_G_cp  (int lev) const { return G_cp[lev].get(); }

    [[nodiscard]] amrex::MultiFab * get_pointer_edge_lengths  (int lev, int direction) const { return m_edge_lengths[lev][direction].get(); }
    [[nodiscard]] amrex::MultiFab * get_pointer_face_areas  (int lev, int direction) const { return m_face_areas[lev][direction].get(); }

with something like:

enum class FieldType
{
    Efield_aux,
    Bfield_aux
    //  ...
};



    template <FieldType Type>
    [[nodiscard]] amrex::MultiFab * get_pointer (int lev, int direction)
    {
        if (auto* ptr = m_multifabs[lev][direction][Type].get(); ptr != nullptr)
            return ptr; 
        else
            WARPX_ABORT_WITH_MESSAGE("...");
    }

?

Copy link
Member

@ax3l ax3l Feb 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, maybe we can call it get_mf_pointer or get_field_pointer?

Not sure the FieldType must be a template - this is not used in hot loops so it can be a regular argument, no?

@@ -1202,7 +1202,7 @@ PhysicalParticleContainer::AddPlasma (PlasmaInjector const& plasma_injector, int
const bool rz_random_theta = m_rz_random_theta;
#endif
amrex::ParallelForRNG(overlap_box,
[=] AMREX_GPU_DEVICE (int i, int j, int k, amrex::RandomEngine const& engine) noexcept
[=] AMREX_GPU_DEVICE (int i, int j, int k, amrex::RandomEngine const& engine) noexcept //NOLINT(clang-analyzer-optin.performance.Padding)
Copy link
Member

@ax3l ax3l Feb 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this belong in AMReX or at least an AMReX issue instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it is something that can happen with any lambda function (e.g., you can have a look here: https://godbolt.org/z/fK6PhvdsG). I suppose it depends on the order in which the variables captured by the lambda function are actually used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's open this as an issue in AMReX, could be interesting for @WeiqunZhang.

@WeiqunZhang
Copy link
Member

WeiqunZhang commented Feb 13, 2024 via email

@lucafedeli88
Copy link
Member Author

WARPX_ALWAYS_ASSERT_WITH_MESSAGE

Very indirectly there is an assert: WARPX_ALWAYS_ASSERT_WITH_MESSAGE calls ablastr::utils::TextMsg::Assert which calls amrex::Assert which finally calls assert. However, ablastr::utils::TextMsg::Assert is in a .cpp file, so the compiler may not be able to figure that out. Should I move it to the corresponding .H file and force inlining?

@WeiqunZhang
Copy link
Member

I don't think it will help, especially when MPI is on, we call MPI_Abort eventually.

Source/WarpX.cpp Fixed Show fixed Hide fixed
@lucafedeli88 lucafedeli88 changed the title [WIP] Clang tidy CI test: add several clang-analyzer-* checks to clang tidy CI test Clang tidy CI test: add several clang-analyzer-* checks to clang tidy CI test Feb 22, 2024
@ax3l
Copy link
Member

ax3l commented Mar 4, 2024

@lucafedeli88 when you rebase against the latest development, your new AMReX assume should be available now. There is also a small merge conflict right now.

@lucafedeli88
Copy link
Member Author

@lucafedeli88 when you rebase against the latest development, your new AMReX assume should be available now. There is also a small merge conflict right now.

@ax3l , I should have fixed the merge conflict

@lucafedeli88
Copy link
Member Author

ping, @ax3l :-) !


enum struct PatchType : int
{
fine,
coarse
};

enum struct FieldType : int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ok for now, but we should make it a runtime construct so we can add more multifabs later on at runtime and also easily name them.

@ax3l ax3l merged commit 0466145 into ECP-WarpX:development Apr 1, 2024
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cleaning Clean code, improve readability component: tests Tests and CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants