Skip to content

Commit 9bb4fa7

Browse files
Merge pull request #219 from mwarusz/omega/wind-forcing-and-bottom-drag
Add wind forcing and bottom drag tendency terms
2 parents 16ee28f + 4c1caf6 commit 9bb4fa7

24 files changed

+1178
-517
lines changed

components/omega/configs/Default.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Omega:
1616
Advection:
1717
FluxThicknessType: Center
1818
FluxTracerType: Center
19+
WindStress:
20+
InterpType: Isotropic
1921
Tendencies:
2022
ThicknessFluxTendencyEnable: true
2123
PVTendencyEnable: true
@@ -26,6 +28,10 @@ Omega:
2628
VelHyperDiffTendencyEnable: true
2729
ViscDel4: 1.2e11
2830
DivFactor: 1.0
31+
WindForcingTendencyEnable: false
32+
Density0: 1026.0
33+
BottomDragTendencyEnable: false
34+
BottomDragCoeff: 0.0
2935
TracerHorzAdvTendencyEnable: true
3036
TracerDiffTendencyEnable: true
3137
EddyDiff2: 10.0
@@ -91,7 +97,7 @@ Omega:
9197
Contents:
9298
- Tracers
9399
- State
94-
- SshCellDefault
100+
- SshCell
95101
Highfreq:
96102
UsePointerFile: false
97103
Filename: ocn.hifreq.$Y-$M

components/omega/doc/devGuide/AuxiliaryVariables.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,6 @@ The following auxiliary variable groups are currently implemented:
101101
|| Del2RelVortVertex ||
102102
| TracerAuxVars | HTracersEdge | Center or Upwind|
103103
|| Del2TracersCell ||
104+
| WindForcingAuxVars | ZonalStressCell ||
105+
|| MeridStressCell ||
106+
|| NormalStressEdge ||

components/omega/doc/devGuide/TendencyTerms.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ implemented:
3838
- `TracerHorzAdvOnCell`
3939
- `TracerDiffOnCell`
4040
- `TracerHyperDiffOnCell`
41+
- `WindForcingOnEdge`
42+
- `BottomDragOnEdge`

components/omega/doc/userGuide/AuxiliaryVariables.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ The following auxiliary variables are currently available:
2929
| VelDel2RelVortVertex | curl of laplacian of horizontal velocity on cells
3030
| HTracersEdge | thickness-weighted tracers used for fluxes through edges. May be centered, upwinded or a combination of the two
3131
| Del2TracersCell | laplacian of tracers on cells
32+
| ZonalStressCell | zonal component of wind stress on cells
33+
| MeridStressCell | meridional component of wind stress on cells
34+
| NormalStressEdge | normal component of wind stress on edge

components/omega/doc/userGuide/TendencyTerms.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ tendency terms are currently implemented:
1717
| TracerHorzAdvOnCell | horizontal advection of thickness-weighted tracers
1818
| TracerDiffOnCell | horizontal diffusion of thickness-weighted tracers
1919
| TracerHyperDiffOnCell | biharmonic horizontal mixing of thickness-weighted tracers
20+
| WindForcingOnEdge | forcing by wind stress, defined on edges
21+
| BottomDragOnEdge | bottom drag, defined on edges
2022

2123
Among the internal data stored by each functor is a `bool` which can enable or
2224
disable the contribution of that particular term to the tendency. These flags
@@ -45,3 +47,6 @@ the currently available tendency terms:
4547
| | EddyDiff2 | horizontal diffusion coefficient
4648
| TracerHyperDiffOnCell | TracerHyperDiffTendencyEnable | enable/disable term
4749
| | EddyDiff4 | biharmonic horizontal mixing coeffienct for tracers
50+
| WindForcingOnEdge | WindForcingTendencyEnable | enable/disable term
51+
| BottomDragOnEdge | BottomDragTendencyEnable | enable/disable term
52+
| | BottomDragCoeff | bottom drag coefficient

components/omega/src/ocn/AuxiliaryState.cpp

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,21 @@ AuxiliaryState *AuxiliaryState::DefaultAuxState = nullptr;
1010
std::map<std::string, std::unique_ptr<AuxiliaryState>>
1111
AuxiliaryState::AllAuxStates;
1212

13+
static std::string stripDefault(const std::string &Name) {
14+
return Name != "Default" ? Name : "";
15+
}
16+
1317
// Constructor. Constructs the member auxiliary variables and registers their
1418
// fields with IOStreams
1519
AuxiliaryState::AuxiliaryState(const std::string &Name, const HorzMesh *Mesh,
16-
int NVertLevels, int NTracers)
17-
: Mesh(Mesh), Name(Name), KineticAux(Name, Mesh, NVertLevels),
18-
LayerThicknessAux(Name, Mesh, NVertLevels),
19-
VorticityAux(Name, Mesh, NVertLevels),
20-
VelocityDel2Aux(Name, Mesh, NVertLevels),
21-
TracerAux(Name, Mesh, NVertLevels, NTracers) {
20+
Halo *MeshHalo, int NVertLevels, int NTracers)
21+
: Mesh(Mesh), MeshHalo(MeshHalo), Name(stripDefault(Name)),
22+
KineticAux(stripDefault(Name), Mesh, NVertLevels),
23+
LayerThicknessAux(stripDefault(Name), Mesh, NVertLevels),
24+
VorticityAux(stripDefault(Name), Mesh, NVertLevels),
25+
VelocityDel2Aux(stripDefault(Name), Mesh, NVertLevels),
26+
WindForcingAux(stripDefault(Name), Mesh),
27+
TracerAux(stripDefault(Name), Mesh, NVertLevels, NTracers) {
2228

2329
GroupName = "AuxiliaryState";
2430
if (Name != "Default") {
@@ -32,6 +38,7 @@ AuxiliaryState::AuxiliaryState(const std::string &Name, const HorzMesh *Mesh,
3238
LayerThicknessAux.registerFields(GroupName, AuxMeshName);
3339
VorticityAux.registerFields(GroupName, AuxMeshName);
3440
VelocityDel2Aux.registerFields(GroupName, AuxMeshName);
41+
WindForcingAux.registerFields(GroupName, AuxMeshName);
3542
TracerAux.registerFields(GroupName, AuxMeshName);
3643
}
3744

@@ -42,6 +49,7 @@ AuxiliaryState::~AuxiliaryState() {
4249
LayerThicknessAux.unregisterFields();
4350
VorticityAux.unregisterFields();
4451
VelocityDel2Aux.unregisterFields();
52+
WindForcingAux.unregisterFields();
4553
TracerAux.unregisterFields();
4654

4755
int Err = FieldGroup::destroy(GroupName);
@@ -64,6 +72,7 @@ void AuxiliaryState::computeMomAux(const OceanState *State, int ThickTimeLevel,
6472
OMEGA_SCOPE(LocLayerThicknessAux, LayerThicknessAux);
6573
OMEGA_SCOPE(LocVorticityAux, VorticityAux);
6674
OMEGA_SCOPE(LocVelocityDel2Aux, VelocityDel2Aux);
75+
OMEGA_SCOPE(LocWindForcingAux, WindForcingAux);
6776

6877
parallelFor(
6978
"vertexAuxState1", {Mesh->NVerticesAll, NChunks},
@@ -82,7 +91,12 @@ void AuxiliaryState::computeMomAux(const OceanState *State, int ThickTimeLevel,
8291
const auto &RelVortVertex = VorticityAux.RelVortVertex;
8392

8493
parallelFor(
85-
"edgeAuxState1", {Mesh->NEdgesAll, NChunks},
94+
"edgeAuxState1", {Mesh->NEdgesAll}, KOKKOS_LAMBDA(int IEdge) {
95+
LocWindForcingAux.computeVarsOnEdge(IEdge);
96+
});
97+
98+
parallelFor(
99+
"edgeAuxState2", {Mesh->NEdgesAll, NChunks},
86100
KOKKOS_LAMBDA(int IEdge, int KChunk) {
87101
LocVorticityAux.computeVarsOnEdge(IEdge, KChunk);
88102
LocLayerThicknessAux.computeVarsOnEdge(IEdge, KChunk, LayerThickCell,
@@ -153,16 +167,17 @@ void AuxiliaryState::computeAll(const OceanState *State,
153167

154168
// Create a non-default auxiliary state
155169
AuxiliaryState *AuxiliaryState::create(const std::string &Name,
156-
const HorzMesh *Mesh, int NVertLevels,
157-
const int NTracers) {
170+
const HorzMesh *Mesh, Halo *MeshHalo,
171+
int NVertLevels, const int NTracers) {
158172
if (AllAuxStates.find(Name) != AllAuxStates.end()) {
159173
LOG_ERROR("Attempted to create a new AuxiliaryState with name {} but it "
160174
"already exists",
161175
Name);
162176
return nullptr;
163177
}
164178

165-
auto *NewAuxState = new AuxiliaryState(Name, Mesh, NVertLevels, NTracers);
179+
auto *NewAuxState =
180+
new AuxiliaryState(Name, Mesh, MeshHalo, NVertLevels, NTracers);
166181
AllAuxStates.emplace(Name, NewAuxState);
167182

168183
return NewAuxState;
@@ -172,12 +187,13 @@ AuxiliaryState *AuxiliaryState::create(const std::string &Name,
172187
// initialized.
173188
void AuxiliaryState::init() {
174189
const HorzMesh *DefMesh = HorzMesh::getDefault();
190+
Halo *DefHalo = Halo::getDefault();
175191

176192
int NVertLevels = DefMesh->NVertLevels;
177193
int NTracers = Tracers::getNumTracers();
178194

179-
AuxiliaryState::DefaultAuxState =
180-
AuxiliaryState::create("Default", DefMesh, NVertLevels, NTracers);
195+
AuxiliaryState::DefaultAuxState = AuxiliaryState::create(
196+
"Default", DefMesh, DefHalo, NVertLevels, NTracers);
181197

182198
Config *OmegaConfig = Config::getOmegaConfig();
183199
DefaultAuxState->readConfigOptions(OmegaConfig);
@@ -248,6 +264,37 @@ void AuxiliaryState::readConfigOptions(Config *OmegaConfig) {
248264
} else {
249265
ABORT_ERROR("AuxiliaryState: Unknown FluxTracerType requested");
250266
}
267+
268+
Config WindStressConfig("WindStress");
269+
Err += OmegaConfig->get(WindStressConfig);
270+
271+
std::string WindStressInterpTypeStr;
272+
Err += WindStressConfig.get("InterpType", WindStressInterpTypeStr);
273+
CHECK_ERROR_ABORT(
274+
Err, "AuxiliaryState: InterpType not found in WindStressConfig");
275+
276+
if (WindStressInterpTypeStr == "Isotropic") {
277+
this->WindForcingAux.InterpChoice = InterpCellToEdgeOption::Isotropic;
278+
} else if (WindStressInterpTypeStr == "Anisotropic") {
279+
this->WindForcingAux.InterpChoice = InterpCellToEdgeOption::Anisotropic;
280+
} else {
281+
ABORT_ERROR("AuxiliaryState: Unknown InterpType requested");
282+
}
251283
}
252284

285+
//------------------------------------------------------------------------------
286+
// Perform auxiliary state halo exchange
287+
// Note that only non-computed auxiliary variables needs to be exchanged
288+
I4 AuxiliaryState::exchangeHalo() {
289+
I4 Err = 0;
290+
291+
Err +=
292+
MeshHalo->exchangeFullArrayHalo(WindForcingAux.ZonalStressCell, OnCell);
293+
Err +=
294+
MeshHalo->exchangeFullArrayHalo(WindForcingAux.MeridStressCell, OnCell);
295+
296+
return Err;
297+
298+
} // end exchangeHalo
299+
253300
} // namespace OMEGA

components/omega/src/ocn/AuxiliaryState.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Config.h"
55
#include "DataTypes.h"
6+
#include "Halo.h"
67
#include "HorzMesh.h"
78
#include "OceanState.h"
89
#include "Tracers.h"
@@ -11,6 +12,7 @@
1112
#include "auxiliaryVars/TracerAuxVars.h"
1213
#include "auxiliaryVars/VelocityDel2AuxVars.h"
1314
#include "auxiliaryVars/VorticityAuxVars.h"
15+
#include "auxiliaryVars/WindForcingAuxVars.h"
1416

1517
#include <memory>
1618
#include <string>
@@ -36,6 +38,7 @@ class AuxiliaryState {
3638
TracerAuxVars TracerAux;
3739
VorticityAuxVars VorticityAux;
3840
VelocityDel2AuxVars VelocityDel2Aux;
41+
WindForcingAuxVars WindForcingAux;
3942

4043
~AuxiliaryState();
4144

@@ -46,7 +49,7 @@ class AuxiliaryState {
4649

4750
// Create a non-default auxiliary state
4851
static AuxiliaryState *create(const std::string &Name, const HorzMesh *Mesh,
49-
int NVertLevels, int NTracers);
52+
Halo *MeshHalo, int NVertLevels, int NTracers);
5053

5154
/// Get the default auxiliary state
5255
static AuxiliaryState *getDefault();
@@ -63,6 +66,9 @@ class AuxiliaryState {
6366
/// Read and set config options
6467
void readConfigOptions(Config *OmegaConfig);
6568

69+
/// Exchange halo
70+
I4 exchangeHalo();
71+
6672
// Compute all auxiliary variables needed for momentum equation
6773
void computeMomAux(const OceanState *State, int ThickTimeLevel,
6874
int VelTimeLevel) const;
@@ -75,13 +81,14 @@ class AuxiliaryState {
7581
int TimeLevel) const;
7682

7783
private:
78-
AuxiliaryState(const std::string &Name, const HorzMesh *Mesh,
84+
AuxiliaryState(const std::string &Name, const HorzMesh *Mesh, Halo *MeshHalo,
7985
int NVertLevels, int NTracers);
8086

8187
AuxiliaryState(const AuxiliaryState &) = delete;
8288
AuxiliaryState(AuxiliaryState &&) = delete;
8389

8490
const HorzMesh *Mesh;
91+
Halo *MeshHalo;
8592
static AuxiliaryState *DefaultAuxState;
8693
static std::map<std::string, std::unique_ptr<AuxiliaryState>> AllAuxStates;
8794
};

components/omega/src/ocn/HorzOperators.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@ TangentialReconOnEdge::TangentialReconOnEdge(HorzMesh const *Mesh)
2121
: NEdgesOnEdge(Mesh->NEdgesOnEdge), EdgesOnEdge(Mesh->EdgesOnEdge),
2222
WeightsOnEdge(Mesh->WeightsOnEdge) {}
2323

24+
InterpCellToEdge::InterpCellToEdge(const HorzMesh *Mesh)
25+
: CellsOnEdge(Mesh->CellsOnEdge), VerticesOnEdge(Mesh->VerticesOnEdge),
26+
CellsOnVertex(Mesh->CellsOnVertex),
27+
KiteAreasOnVertex(Mesh->KiteAreasOnVertex),
28+
VertexDegree(Mesh->VertexDegree) {}
29+
2430
} // namespace OMEGA

components/omega/src/ocn/HorzOperators.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,57 @@ class TangentialReconOnEdge {
132132
Array2DReal WeightsOnEdge;
133133
};
134134

135+
enum class InterpCellToEdgeOption { Anisotropic, Isotropic };
136+
137+
class InterpCellToEdge {
138+
public:
139+
InterpCellToEdge(const HorzMesh *Mesh);
140+
141+
KOKKOS_FUNCTION Real operator()(int IEdge, const Array1DReal &ArrayCell,
142+
InterpCellToEdgeOption Option) const {
143+
switch (Option) {
144+
case InterpCellToEdgeOption::Anisotropic:
145+
return interpolateAnisotropic(IEdge, ArrayCell);
146+
case InterpCellToEdgeOption::Isotropic:
147+
return interpolateIsotropic(IEdge, ArrayCell);
148+
}
149+
};
150+
151+
KOKKOS_FUNCTION Real
152+
interpolateAnisotropic(int IEdge, const Array1DReal &ArrayCell) const {
153+
const int JCell0 = CellsOnEdge(IEdge, 0);
154+
const int JCell1 = CellsOnEdge(IEdge, 1);
155+
156+
return 0.5_Real * (ArrayCell(JCell0) + ArrayCell(JCell1));
157+
};
158+
159+
KOKKOS_FUNCTION Real
160+
interpolateIsotropic(int IEdge, const Array1DReal &ArrayCell) const {
161+
162+
Real Accum = 0;
163+
Real AreaAccum = 0;
164+
for (int J = 0; J < 2; ++J) {
165+
const int JVertex = VerticesOnEdge(IEdge, J);
166+
for (int L = 0; L < VertexDegree; ++L) {
167+
const Real KiteArea = KiteAreasOnVertex(JVertex, L);
168+
const int LCell = CellsOnVertex(JVertex, L);
169+
170+
Accum += ArrayCell(LCell) * KiteArea;
171+
AreaAccum += KiteArea;
172+
}
173+
}
174+
175+
const Real InvAreaAccum = 1._Real / AreaAccum;
176+
return Accum * InvAreaAccum;
177+
};
178+
179+
private:
180+
Array2DI4 CellsOnEdge;
181+
Array2DI4 VerticesOnEdge;
182+
Array2DI4 CellsOnVertex;
183+
Array2DReal KiteAreasOnVertex;
184+
I4 VertexDegree;
185+
};
186+
135187
} // namespace OMEGA
136188
#endif

components/omega/src/ocn/OceanInit.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,17 @@ int initOmegaModules(MPI_Comm Comm) {
157157
}
158158
}
159159

160-
// Update Halos and Host arrays with new state and tracer fields
160+
// Update Halos and Host arrays with new state, auxiliary state, and tracer
161+
// fields
161162

162163
OceanState *DefState = OceanState::getDefault();
163164
I4 CurTimeLevel = 0;
164165
DefState->exchangeHalo(CurTimeLevel);
165166
DefState->copyToHost(CurTimeLevel);
166167

168+
AuxiliaryState *DefAuxState = AuxiliaryState::getDefault();
169+
DefAuxState->exchangeHalo();
170+
167171
// Now update tracers - assume using same time level index
168172
Err = Tracers::exchangeHalo(CurTimeLevel);
169173
if (Err != 0) {

0 commit comments

Comments
 (0)