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

Chunk initial topography #1705

Closed
wants to merge 68 commits into from

Conversation

anne-glerum
Copy link
Contributor

@gassmoeller
Hi Rene,
do you think you could give this geometry model a try? I've added a test that you could run. Also, right now, that test fails on my laptop because I put in an AssertThrow for older deal.II versions that try to add non-zero initial topography. What would be the best way to go around this?
I'd like a more compact way to put in the derivative gradient, but that's for tomorrow :)
Thank you!

Copy link
Member

@gassmoeller gassmoeller left a comment

Choose a reason for hiding this comment

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

The current version does not run, but instead creates the following error:

--------------------------------------------------------
An error occurred in line <6280> of file </home/rengas/Software/dealii/include/deal.II/numerics/vector_tools.templates.h> in function
    void dealii::VectorTools::compute_nonzero_normal_flux_constraints(const DoFHandlerType<dim, spacedim>&, unsigned int, const std::set<unsigned char>&, typename dealii::FunctionMap<spacedim>::type&, dealii::ConstraintMatrix&, const dealii::Mapping<dim, spacedim>&) [with int dim = 2; int spacedim = 2; DoFHandlerType = dealii::DoFHandler; typename dealii::FunctionMap<spacedim>::type = std::map<unsigned char, const dealii::Function<2>*, std::less<unsigned char>, std::allocator<std::pair<const unsigned char, const dealii::Function<2>*> > >]
The violated condition was: 
    std::fabs(determinant (t)) > 1e-3
Additional information: 
    Found a set of normal vectors that are nearly collinear.

Stacktrace:
-----------
#0  /home/rengas/Software/deal.II-dev/lib/libdeal_II.g.so.9.0.0-pre: void dealii::VectorTools::compute_nonzero_normal_flux_constraints<2, 2, dealii::DoFHandler>(dealii::DoFHandler<2, 2> const&, unsigned int, std::set<unsigned char, std::less<unsigned char>, std::allocator<unsigned char> > const&, dealii::FunctionMap<2, double>::type&, dealii::ConstraintMatrix&, dealii::Mapping<2, 2> const&)
#1  /home/rengas/Software/deal.II-dev/lib/libdeal_II.g.so.9.0.0-pre: void dealii::VectorTools::compute_no_normal_flux_constraints<2, 2, dealii::DoFHandler>(dealii::DoFHandler<2, 2> const&, unsigned int, std::set<unsigned char, std::less<unsigned char>, std::allocator<unsigned char> > const&, dealii::ConstraintMatrix&, dealii::Mapping<2, 2> const&)
#2  aspect: aspect::Simulator<2>::setup_dofs()
#3  aspect: aspect::Simulator<2>::run()
#4  aspect: main
--------------------------------------------------------

I was hoping to find a clue about the problem by reviewing the code, but it is not obvious to me where the problem is. One clue is that if I remove the tangential velocity boundaries the model runs, and it does not seem to produce any topography independent on the size of topography I prescribe in the data file. Need to take a closer look in the next days, but feel free to go ahead and fix my comments, maybe you notice something that is not right.

@@ -134,6 +132,11 @@ namespace aspect
double depth(const Point<dim> &position) const;

virtual
double depth_wrt_topo(const Point<dim> &position) const;
Copy link
Member

Choose a reason for hiding this comment

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

Please add documentation

@@ -269,6 +272,13 @@ namespace aspect
public:
ChunkGeometry();

/**
* An initialization function necessary for to make sure that the
Copy link
Member

Choose a reason for hiding this comment

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

necessary to


virtual
Point<dim>
push_forward_topo(const Point<dim> &chart_point) const;
Copy link
Member

Choose a reason for hiding this comment

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

Please add documentation to all of the functions above. You can copy a lot from EllipsoidalChunk

@@ -68,6 +68,12 @@ namespace aspect
double
value (const Point<dim-1> &p) const;

/**
* Return the gradient of the surface topography for a given position along
* along the surface.
Copy link
Member

Choose a reason for hiding this comment

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

double along

* Return the value of the elevation at the given point.
*/
// virtual
// Tensor<1,dim-1> vector_gradient (const Point<dim> &p) const = 0;
Copy link
Member

Choose a reason for hiding this comment

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

What about this function?

Copy link
Member

Choose a reason for hiding this comment

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

I think this function is still here and unnecessary?

Point<dim> topor_phi_theta = r_phi_theta;
topor_phi_theta[0] = topo_radius;
return topor_phi_theta;
// return r_phi_theta;
Copy link
Member

Choose a reason for hiding this comment

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

remove the comment

// Convert latitude to colatitude
if (dim == 3)
surface_point[1] = 0.5*numbers::PI - surface_point[1];
topography = topo->value(surface_point);
Copy link
Member

Choose a reason for hiding this comment

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

make to const double topography

Point<dim> r_phi_theta = topor_phi_theta;
r_phi_theta[0] = radius;
return r_phi_theta;
// return topor_phi_theta;
Copy link
Member

Choose a reason for hiding this comment

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

remove comment

@@ -291,6 +542,7 @@ namespace aspect
}

// Attach shell boundary objects to the curved inner and outer boundaries
// TODO is this boundary still correct for a displaced mesh?
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 not used with a displaced mesh (only for deal.II >9.0). Or do you mean in case of a free surface unrelated to initial topography?

// depth is therefore always positive
const double outer_radius = manifold.get_radius(position);
const Point<dim> rtopo_phi_theta = manifold.pull_back_sphere(position);
return std::max(0.0, outer_radius - rtopo_phi_theta[0]);
Copy link
Member

Choose a reason for hiding this comment

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

This way you cut off all depth values above the unmodified surface, is that what you want? depth_wrt_topo suggests to me to use the full manifold.pull_back, or do I misunderstand?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Depth here is computed as the difference between the radius of modified surface (given by get_radius) and the modified point (given by pull_back_sphere).

@anne-glerum
Copy link
Contributor Author

anne-glerum commented May 24, 2017

@gassmoeller Thanks for testing! I'll have a look today, now that I can test both versions.

Update:
Enabling topography for pre-dealII 9 shows that when the coarse grid is created, get_time() still holds a quiet_nan, hence AsciiDataBoundary returns 0 (see also the discussion in the box_initial_topography pr #1187). Later calls to push_forward and pull_back do use a non-zero topography value, and I guess this creates problems.

Enabling the AsciiDataBoundary::get_data_component function to return the correct value, results in added initial topography. However, when this topography is not the same everywhere, the HyperShellBoundary complains (because not all points lie on the same radius). When we remove this boundary object from the upper boundary, any initial topography can be set. (The ellipsoidal chunk does not set boundary objects, so it doesn’t complain about initial topography.)

As we will not use initial topography with the old boundary objects, I’ll leave this as is. The AsciiDataBoundary::get_data_component() dependence on get_time() is still problematic for the manifold however, and I'm wondering whether to use a signal like for the box topography (signals.pre_set_initial_state (triangulation) in core.cc) or to adapt the get_data_component() function.

@gassmoeller
Copy link
Member

Great, that sounds like you found the problem 👍. Let us stay consistent and use the signal to work around it. I do not quite remember the logic in AsciiDataBoundary::get_data_component, but I remember there were a lot of special cases to consider, and it is complicated enough already.
How did you end up running into the HyperShellBoundary error? Should not the boundary objects only be created and attached if we use deal.II < 9.0, and the initial topography only be used with deal.II >= 9.0?

@gassmoeller
Copy link
Member

/run-tests

@anne-glerum
Copy link
Contributor Author

Alright, I'll try and use the signal and address your comments.

I ran into the HyperShellBoundary error when I enabled initial topography with deal.II < 9.0 (because I knew this used to work).

@anne-glerum
Copy link
Contributor Author

anne-glerum commented May 25, 2017

@gassmoeller This functionality now also works for dealii 9-pre.

Three things:

  1. In a model without driving forces (i.e. the test case), a constant topography gives very small residual velocities. A constant topography gradient gives somewhat bigger, uniform velocities in the surface elements, but varying gradients result in anomalies at the transition between different topography values. These anomalies get smaller with resolution, see figure. The normal vectors look correct upon visual inspection. I wonder this whether this is somehow related to the velocity anomalies along the curved boundaries in 3D, or just the effect of the abrupt change in gradient at these points.
    chunk_topo_resolution

chunk_topo_normals

  1. Is there a way to make the test pass with all dealii versions?

  2. I've not yet used the signal in core.cc as we decided on for the box geometry for 2 reasons. For the box it is actually necessary to apply the initial topography after the initial mesh refinement to get a good representation of the prescribed topography, for the chunk it is not. Also, doing it after initial mesh refinement, requires extra steps: instead of just calling push_forward in the create_coarse_mesh function, the grid in cartesian coordinates needs to be transformed to spherical without adding topography, then the push forward transformation needs to be done with topography when the signal is called. And I just wanted to make it work first :)

@anne-glerum
Copy link
Contributor Author

anne-glerum commented Apr 5, 2019

Hi @gassmoeller @naliboff , I've rebased, updated and simplified this pr and I think it's ready for another review. Repeating the test of which I posted figures above, now results in a flow field from high to low topography (velocity field and vectors):
chunk_sphere_extremetopo_noblob_v
The tester fails as the test only works for dealii >=9, while the tester uses dealii 8.5. Is there a way to only run a test for a specific dealii version?

@anne-glerum
Copy link
Contributor Author

For reference, I'm posting some snapshots of 1 timestep chunk models with varying resolution/refinement/topography using the updates in this pr. Models are based on the testchunk_topography_postprocessor.prm (rising blob, no slip BC except for free surface).

No topography, only global refinement (bottom) or with adaptive refinement (top), refinement increases to the right:
chunk_sphere_notopo_ref_amr
chunk_sphere_notopo_ref_amr_strianrate
Comparison of chunk (top) and shell (bottom) for adaptive refinement and without topography:
chunk_shell_sphere_notopo_ref_amr_vel
chunk_shell_sphere_notopo_ref_amr_strainrate
Chunk with global refinement with initial topography without (top) and with (bottom) a rising sphere:
chunk_sphere_topo_noblob_ref_v

@naliboff
Copy link
Contributor

@anne-glerum - Thanks for updating all of this! I compiled the branch to run a few tests, but unfortunately both the 2D chunk and the models I made are failing at this line in utilities.cc:

      if (this->get_time() - first_data_file_model_time >= 0.0 ||
          (dynamic_cast<const GeometryModel::Chunk<dim>*>(&this->get_geometry_model()) != 0 &&
           dynamic_cast<const InitialTopographyModel::AsciiData<dim>*>(&this->get_initial_topography_model()) != 0 &&
           std::isnan(this->get_time())))

Is the test successfully running on your end? If so, perhaps it is a deal.II version issue?

@anne-glerum
Copy link
Contributor Author

Hi @naliboff , yes the test works for me. What error message do you get?

@naliboff
Copy link
Contributor

naliboff commented May 6, 2019

@anne-glerum The error message is just a floating point exception, but clearly no division by zero in the failing line. Perhaps the initial data file model time may not be initialized yet? Let me know if digging deeper would be helpful!

FYI, I built the branch with deal.II v9.0.1.

Thread 1 "aspect" received signal SIGFPE, Arithmetic exception.
0x000055555613760b in aspect::Utilities::AsciiDataBoundary<2>::get_data_component (this=this@entry=0x5555568cdc20, 
    boundary_indicator=<optimized out>, position=..., component=component@entry=0)
    at /data1/Software/aspect/chunk_initial_topo/aspect/source/utilities.cc:2177
2177	      if (this->get_time() - first_data_file_model_time >= 0.0 ||
(gdb) 

@anne-glerum
Copy link
Contributor Author

@naliboff I've switched the conditional statements. Only in the very specific case of Initial topography specified by an ascii data table, we should get to these lines before time is set to something other than NaN. Now we should hit the condition that checks for NaN first and hopefully that solves the problem. If not, some more info would be helpful and I'll try to reproduce the error.

@naliboff
Copy link
Contributor

naliboff commented May 7, 2019

@anne-glerum - hmmm, still getting the same error with the last commit. I'll dig into the debugger tomorrow and see if I can pinpoint a solution on my end.

@anne-glerum anne-glerum changed the title [WIP] Chunk initial topography Chunk initial topography May 22, 2019
@anne-glerum
Copy link
Contributor Author

anne-glerum commented May 22, 2019

new is_time_initialized parameter could be updated after new function discussed in #2529.

Actually, we could use get_timestep_number() == numbers::invalid_unsigned_int

Copy link
Member

@gassmoeller gassmoeller left a comment

Choose a reason for hiding this comment

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

Looks generally good. I would like to take another look after you address the comments, but nothing serious.

* Return the value of the elevation at the given point.
*/
// virtual
// Tensor<1,dim-1> vector_gradient (const Point<dim> &p) const = 0;
Copy link
Member

Choose a reason for hiding this comment

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

I think this function is still here and unnecessary?

private:
// The minimum longitude of the domain
double point1_lon;
double inner_radius;

double max_depth;
Copy link
Member

Choose a reason for hiding this comment

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

Please add comments for max_depth and inner_radius

/**
* Returns the gradient of the function based on the bilinear
* interpolation of the data (velocity, temperature, etc. - according
* to the used plugin) in Cartesian coordinates. TOOD Cartesian??
Copy link
Member

Choose a reason for hiding this comment

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

Remove TODO

@@ -32,6 +33,10 @@
#include <deal.II/grid/tria_boundary_lib.h>
#endif

#if DEAL_II_VERSION_GTE(9,0,0)
Copy link
Member

Choose a reason for hiding this comment

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

No need for DEAL_II_VERSION_GTE(9,0,0) anymore, because we now require 9.0.


// prior to deal.II 9, we do not apply initial topography
#if !DEAL_II_VERSION_GTE(9,0,0)
const double phi = chart_point[1]; // Longitude
Copy link
Member

Choose a reason for hiding this comment

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

This case no longer happens, remove the if and the line.

@@ -1829,7 +1838,6 @@ namespace aspect
}



Copy link
Member

Choose a reason for hiding this comment

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

keep the line

@@ -2165,7 +2173,11 @@ namespace aspect
const Point<dim> &position,
const unsigned int component) const
{
if (this->get_time() - first_data_file_model_time >= 0.0)
// For initial ascii data topography, we need access to the data before get_time() is set
if ( (dynamic_cast<const GeometryModel::Chunk<dim>*>(&this->get_geometry_model()) != nullptr &&
Copy link
Member

Choose a reason for hiding this comment

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

please add a comment why these geometries are special

return time_weight * gradients + (1 - time_weight) * old_gradients;
}
else
return Tensor<1,dim-1>();
Copy link
Member

Choose a reason for hiding this comment

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

This way you silently return 0.0 for other geometries than the Chunk? Please make this an AssertThrow(false, ...) so that nobody accidentally calls this function for other geometries.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think return this Tensor makes sense for the other condition (this->get_time() - first_data_file_model_time >= 0.0). Then if we're not far enough in time yet, 0 is returned. The same is done for get_data_component.


// Grab lon,lat coordinates
Point<dim-1> surface_point;
for (unsigned int d=0; d<dim-1; d++)
Copy link
Member

Choose a reason for hiding this comment

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

just for convention ++d

@@ -186,7 +340,6 @@ namespace aspect
}



#if DEAL_II_VERSION_GTE(9,0,0)
Copy link
Member

Choose a reason for hiding this comment

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

can remove the ifdef

@anne-glerum
Copy link
Contributor Author

@gassmoeller I've addressed the comments.

@anne-glerum
Copy link
Contributor Author

This PR has been superseded by #3039, so I'm closing it.

@anne-glerum anne-glerum closed this Jun 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants