-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d9f2848
commit 9e0b26d
Showing
5 changed files
with
221 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
/* | ||
* (C) Copyright 2023 ECMWF. | ||
* | ||
* This software is licensed under the terms of the Apache Licence Version 2.0 | ||
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
* In applying this licence, ECMWF does not waive the privileges and immunities | ||
* granted to it by virtue of its status as an intergovernmental organisation | ||
* nor does it submit to any jurisdiction. | ||
*/ | ||
|
||
#include <cmath> | ||
|
||
#include "atlas/util/Constants.h" | ||
|
||
#include "atlas/util/function/SolidBodyRotation.h" | ||
|
||
namespace atlas { | ||
|
||
namespace util { | ||
|
||
namespace function { | ||
|
||
SolidBodyRotation::SolidBodyRotation(const double beta, const double radius) { | ||
sin_beta_ = std::sin(beta * Constants::degreesToRadians()); | ||
cos_beta_ = std::cos(beta * Constants::degreesToRadians()); | ||
radius_ = radius; | ||
} | ||
|
||
void SolidBodyRotation::wind(const double lon, const double lat, double& u, double& v) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double y = lat * Constants::degreesToRadians(); | ||
double cos_x = std::cos(x); | ||
double cos_y = std::cos(y); | ||
double sin_x = std::sin(x); | ||
double sin_y = std::sin(y); | ||
u = cos_y * cos_beta_ + cos_x * sin_y * sin_beta_; | ||
v = -sin_x * sin_beta_; | ||
} | ||
|
||
double SolidBodyRotation::u(const double lon, const double lat) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double y = lat * Constants::degreesToRadians(); | ||
double cos_x = std::cos(x); | ||
double cos_y = std::cos(y); | ||
double sin_y = std::sin(y); | ||
return cos_y * cos_beta_ + cos_x * sin_y * sin_beta_; | ||
} | ||
|
||
double SolidBodyRotation::v(const double lon, const double lat) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double sin_x = std::sin(x); | ||
return -sin_x * sin_beta_; | ||
} | ||
|
||
void SolidBodyRotation::vordiv(const double lon, const double lat, double& vor, double& div) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double y = lat * Constants::degreesToRadians(); | ||
|
||
double cos_x = std::cos(x); | ||
double cos_y = std::cos(y); | ||
double sin_x = std::sin(x); | ||
double sin_y = std::sin(y); | ||
|
||
// Divergence = 1./(R*cos(y)) * ( d/dx( u ) + d/dy( v * cos(y) ) ) | ||
// Vorticity = 1./(R*cos(y)) * ( d/dx( v ) - d/dy( u * cos(y) ) ) | ||
double ddx_u = -sin_x * sin_y * sin_beta_; | ||
double ddy_cosy_v = (-sin_x * sin_beta_) * (-sin_y); | ||
double ddx_v = -cos_x * sin_beta_; | ||
double ddy_cosy_u = | ||
2 * cos_y * (-sin_y) * cos_beta_ + (-sin_y) * cos_x * sin_y * sin_beta_ + cos_y * cos_x * cos_y * sin_beta_; | ||
|
||
double metric = 1. / (radius_ * cos_y); | ||
|
||
div = metric * (ddx_u + ddy_cosy_v); | ||
vor = metric * (ddx_v - ddy_cosy_u); | ||
} | ||
|
||
double SolidBodyRotation::vorticity(const double lon, const double lat) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double y = lat * Constants::degreesToRadians(); | ||
|
||
double cos_x = std::cos(x); | ||
double cos_y = std::cos(y); | ||
double sin_y = std::sin(y); | ||
|
||
// Vorticity = 1./(R*cos(y)) * ( d/dx( v ) - d/dy( u * cos(y) ) ) | ||
double ddx_v = -cos_x * sin_beta_; | ||
double ddy_cosy_u = | ||
2 * cos_y * (-sin_y) * cos_beta_ + (-sin_y) * cos_x * sin_y * sin_beta_ + cos_y * cos_x * cos_y * sin_beta_; | ||
|
||
double metric = 1. / (radius_ * cos_y); | ||
|
||
return metric * (ddx_v - ddy_cosy_u); | ||
} | ||
|
||
double SolidBodyRotation::divergence(const double lon, const double lat) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double y = lat * Constants::degreesToRadians(); | ||
|
||
double cos_y = std::cos(y); | ||
double sin_x = std::sin(x); | ||
double sin_y = std::sin(y); | ||
|
||
// Divergence = 1./(R*cos(y)) * ( d/dx( u ) + d/dy( v * cos(y) ) ) | ||
double ddx_u = -sin_x * sin_y * sin_beta_; | ||
double ddy_cosy_v = (-sin_x * sin_beta_) * (-sin_y); | ||
|
||
double metric = 1. / (radius_ * cos_y); | ||
|
||
return metric * (ddx_u + ddy_cosy_v); | ||
} | ||
|
||
double SolidBodyRotation::windMagnitude(const double lon, const double lat) const { | ||
return std::sqrt(windMagnitudeSquared(lon, lat)); | ||
} | ||
|
||
double SolidBodyRotation::windMagnitudeSquared(const double lon, const double lat) const { | ||
double u, v; | ||
wind(lon, lat, u, v); | ||
return u * u + v * v; | ||
} | ||
|
||
void SolidBodyRotation::windMagnitudeSquaredGradient(const double lon, const double lat, double& dfdx, double& dfdy) const { | ||
double x = lon * Constants::degreesToRadians(); | ||
double y = lat * Constants::degreesToRadians(); | ||
|
||
double cos_x = std::cos(x); | ||
double cos_y = std::cos(y); | ||
double sin_x = std::sin(x); | ||
double sin_y = std::sin(y); | ||
|
||
double metric_y = 1. / radius_; | ||
double metric_x = metric_y / cos_y; | ||
|
||
double u = cos_y * cos_beta_ + cos_x * sin_y * sin_beta_; | ||
double v = -sin_x * sin_beta_; | ||
double dudx = metric_x * (-sin_x * sin_y * sin_beta_); | ||
double dudy = metric_y * (-sin_y * cos_beta_ + cos_x * cos_y * sin_beta_); | ||
double dvdx = metric_x * (-cos_x * sin_beta_); | ||
double dvdy = metric_y * (0.); | ||
dfdx = 2 * u * dudx + 2 * v * dvdx; | ||
dfdy = 2 * u * dudy + 2 * v * dvdy; | ||
} | ||
|
||
} // namespace function | ||
|
||
} // namespace util | ||
|
||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* (C) Copyright 2023 ECMWF. | ||
* | ||
* This software is licensed under the terms of the Apache Licence Version 2.0 | ||
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
* In applying this licence, ECMWF does not waive the privileges and immunities | ||
* granted to it by virtue of its status as an intergovernmental organisation nor | ||
* does it submit to any jurisdiction. | ||
*/ | ||
|
||
|
||
#pragma once | ||
|
||
namespace atlas { | ||
|
||
namespace util { | ||
|
||
namespace function { | ||
|
||
/// \brief An analytic function that provides solid body rotation winds on a sphere. | ||
/// | ||
/// All angles must be provided in degrees. | ||
/// | ||
class SolidBodyRotation { | ||
public: | ||
|
||
SolidBodyRotation() : SolidBodyRotation(0., 1.) {} | ||
|
||
|
||
SolidBodyRotation(const double beta) : SolidBodyRotation(beta, 1.) {} | ||
SolidBodyRotation(const double beta, const double radius); | ||
|
||
void wind(const double lon, const double lat, double& u, double& v) const; | ||
void vordiv(const double lon, const double lat, double& vor, double& div) const; | ||
double windMagnitude(const double lon, const double lat) const; | ||
double u(const double lon, const double lat) const; | ||
double v(const double lon, const double lat) const; | ||
double vorticity(const double lon, const double lat) const; | ||
double divergence(const double lon, const double lat) const; | ||
|
||
double windMagnitudeSquared(const double lon, const double lat) const; | ||
void windMagnitudeSquaredGradient(const double lon, const double lat, double& dfdx, double& dfdy) const; | ||
|
||
private: | ||
double sin_beta_; | ||
double cos_beta_; | ||
double radius_; | ||
}; | ||
|
||
} // namespace function | ||
|
||
} // namespace util | ||
|
||
} // namespace atlas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters