Skip to content

Commit

Permalink
Added adjoint sources
Browse files Browse the repository at this point in the history
- Methods to read adjoint source file
- User Defined sources
  • Loading branch information
Rohit-Kakodkar committed Mar 27, 2024
1 parent 409a352 commit 90129c9
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 20 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ add_library(
src/source/force_source.cpp
src/source/moment_tensor_source.cpp
src/source/adjoint_source.cpp
src/source/external.cpp
src/source/read_sources.cpp
)

Expand Down
4 changes: 2 additions & 2 deletions include/compute/sources/impl/source_medium.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ specfem::compute::impl::sources::source_medium<Dimension, Medium>::
sources.size(), medium_type::components),
h_source_time_function(Kokkos::create_mirror_view(source_time_function)),
source_array("specfem::sources::source_array", sources.size(),
mesh.quadratures.gll.N, mesh.quadratures.gll.N,
medium_type::components),
medium_type::components, mesh.quadratures.gll.N,
mesh.quadratures.gll.N),
h_source_array(Kokkos::create_mirror_view(source_array)) {

for (int isource = 0; isource < sources.size(); isource++) {
Expand Down
2 changes: 1 addition & 1 deletion include/domain/impl/sources/kernel.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void specfem::domain::impl::kernels::source_kernel<
const specfem::kokkos::array_type<type_real,
medium_type::components>
lagrange_interpolant(Kokkos::subview(
sources.source_array, isource_l, iz, ix, Kokkos::ALL));
sources.source_array, isource_l, Kokkos::ALL, iz, ix));

// Source time function
// For acoustic medium, forward simulation, divide by kappa
Expand Down
3 changes: 3 additions & 0 deletions include/kokkos_abstractions.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ template <typename T, int N> struct array_type {
template <typename MemorySpace, typename Layout, typename MemoryTraits>
KOKKOS_INLINE_FUNCTION
array_type(const Kokkos::View<T *, Layout, MemorySpace, MemoryTraits> view) {
#ifndef NDEBUG
assert(view.extent(0) == N);
#endif
for (int i = 0; i < N; ++i) {
data[i] = view(i);
}
Expand Down
2 changes: 2 additions & 0 deletions include/source/adjoint_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class adjoint_source : public source {
return specfem::wavefield::type::adjoint;
}

std::string print() const override;

private:
std::string station_name;
std::string network_name;
Expand Down
39 changes: 39 additions & 0 deletions include/source/external.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef _SPECFEM_SOURCES_EXTERNAL_HPP1_
#define _SPECFEM_SOURCES_EXTERNAL_HPP1_

#include "compute/compute_mesh.hpp"
#include "compute/compute_partial_derivatives.hpp"
#include "compute/properties/properties.hpp"
#include "source.hpp"
#include "yaml-cpp/yaml.h"

namespace specfem {
namespace sources {
class external : public source {
public:
external(){};

external(YAML::Node &Node, const int nsteps, const type_real dt,
const specfem::wavefield::type wavefield_type)
: wavefield_type(wavefield_type), specfem::sources::source(Node, nsteps,
dt){};

void compute_source_array(
const specfem::compute::mesh &mesh,
const specfem::compute::partial_derivatives &partial_derivatives,
const specfem::compute::properties &properties,
specfem::kokkos::HostView3d<type_real> source_array) override;

specfem::wavefield::type get_wavefield_type() const override {
return wavefield_type;
}

std::string print() const override;

private:
specfem::wavefield::type wavefield_type;
};
} // namespace sources
} // namespace specfem

#endif /* _SPECFEM_SOURCES_EXTERNAL_HPP_ */
1 change: 1 addition & 0 deletions include/source/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _SOURCE_INTERFACE_HPP

#include "adjoint_source.hpp"
#include "external.hpp"
#include "force_source.hpp"
#include "moment_tensor_source.hpp"
#include "read_sources.hpp"
Expand Down
2 changes: 2 additions & 0 deletions include/source_time_function/external.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class external : public stf {
return ss.str();
}

type_real get_t0() const override { return this->__t0; }

private:
int __nsteps;
type_real __t0;
Expand Down
3 changes: 2 additions & 1 deletion src/reader/seismogram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ void specfem::reader::seismogram::read() {

while (std::getline(file, line)) {
std::istringstream iss(line);
type_real time, value;
double time, value;
if (!(iss >> time >> value)) {
throw std::runtime_error("Seismogram file " + filename +
" is not formatted correctly");
}

source_time_function(nsteps, 0) = time;
source_time_function(nsteps, 1) = value;
nsteps++;
}

file.close();
Expand Down
40 changes: 31 additions & 9 deletions src/source/adjoint_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void specfem::sources::adjoint_source::compute_source_array(
const auto N = mesh.quadratures.gll.N;

const auto el_type = properties.h_element_types(lcoord.ispec);
const int ncomponents = source_array.extent(0);

// Compute lagrange interpolants at the source location
auto [hxi_source, hpxi_source] =
Expand All @@ -31,17 +32,38 @@ void specfem::sources::adjoint_source::compute_source_array(
for (int ix = 0; ix < N; ++ix) {
hlagrange = hxi_source(ix) * hgamma_source(iz);

if (el_type == specfem::element::medium_tag::acoustic ||
(el_type == specfem::element::medium_tag::elastic &&
specfem::globals::simulation_wave == specfem::wave::sh)) {
if (el_type == specfem::element::medium_tag::acoustic) {
if (ncomponents != 1) {
throw std::runtime_error(
"Force source requires 1 component for acoustic medium");
}
source_array(0, iz, ix) = hlagrange;
source_array(1, iz, ix) = 0;
} else if ((el_type == specfem::element::medium_tag::elastic &&
specfem::globals::simulation_wave == specfem::wave::p_sv) ||
el_type == specfem::element::medium_tag::poroelastic) {
source_array(0, iz, ix) = hlagrange;
source_array(1, iz, ix) = hlagrange;
} else if ((el_type == specfem::element::medium_tag::elastic) ||
(el_type == specfem::element::medium_tag::poroelastic)) {
if (ncomponents != 2) {
throw std::runtime_error(
"Force source requires 2 components for elastic medium");
}
if (specfem::globals::simulation_wave == specfem::wave::sh) {
source_array(0, iz, ix) = hlagrange;
source_array(1, iz, ix) = 0;
} else {
source_array(0, iz, ix) = hlagrange;
source_array(1, iz, ix) = hlagrange;
}
}
}
}
};

std::string specfem::sources::adjoint_source::print() const {

std::ostringstream message;
message << "- Adjoint Source: \n"
<< " Source Location: \n"
<< " x = " << type_real(this->x) << "\n"
<< " z = " << type_real(this->z) << "\n"
<< " Source Time Function: \n"
<< this->forcing_function->print() << "\n";
return message.str();
}
83 changes: 83 additions & 0 deletions src/source/external.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include "algorithms/locate_point.hpp"
#include "compute/compute_mesh.hpp"
#include "compute/compute_partial_derivatives.hpp"
#include "compute/properties/properties.hpp"
#include "enumerations/specfem_enums.hpp"
#include "globals.h"
#include "kokkos_abstractions.h"
#include "point/coordinates.hpp"
#include "quadrature/interface.hpp"
#include "source/interface.hpp"
#include "source_time_function/interface.hpp"
#include "specfem_mpi/interface.hpp"
#include "specfem_setup.hpp"
// #include "utilities.cpp"
#include "yaml-cpp/yaml.h"
#include <cmath>

void specfem::sources::external::compute_source_array(
const specfem::compute::mesh &mesh,
const specfem::compute::partial_derivatives &partial_derivatives,
const specfem::compute::properties &properties,
specfem::kokkos::HostView3d<type_real> source_array) {

specfem::point::gcoord2 coord = specfem::point::gcoord2(this->x, this->z);
auto lcoord = specfem::algorithms::locate_point(coord, mesh);

const auto xi = mesh.quadratures.gll.h_xi;
const auto gamma = mesh.quadratures.gll.h_xi;
const auto N = mesh.quadratures.gll.N;

const auto el_type = properties.h_element_types(lcoord.ispec);
const int ncomponents = source_array.extent(0);

// Compute lagrange interpolants at the source location
auto [hxi_source, hpxi_source] =
specfem::quadrature::gll::Lagrange::compute_lagrange_interpolants(
lcoord.xi, N, xi);
auto [hgamma_source, hpgamma_source] =
specfem::quadrature::gll::Lagrange::compute_lagrange_interpolants(
lcoord.gamma, N, gamma);

type_real hlagrange;

for (int iz = 0; iz < N; ++iz) {
for (int ix = 0; ix < N; ++ix) {
hlagrange = hxi_source(ix) * hgamma_source(iz);

if (el_type == specfem::element::medium_tag::acoustic) {
if (ncomponents != 1) {
throw std::runtime_error(
"Force source requires 1 component for acoustic medium");
}
source_array(0, iz, ix) = hlagrange;
} else if ((el_type == specfem::element::medium_tag::elastic) ||
(el_type == specfem::element::medium_tag::poroelastic)) {
if (ncomponents != 2) {
throw std::runtime_error(
"Force source requires 2 components for elastic medium");
}
if (specfem::globals::simulation_wave == specfem::wave::sh) {
source_array(0, iz, ix) = hlagrange;
source_array(1, iz, ix) = 0;
} else {
source_array(0, iz, ix) = hlagrange;
source_array(1, iz, ix) = hlagrange;
}
}
}
}
};

std::string specfem::sources::external::print() const {

std::ostringstream message;
message << "- External Source: \n"
<< " Source Location: \n"
<< " x = " << type_real(this->x) << "\n"
<< " z = " << type_real(this->z) << "\n"
<< " Source Time Function: \n"
<< this->forcing_function->print() << "\n";

return message.str();
}
2 changes: 1 addition & 1 deletion src/source/force_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void specfem::sources::force::compute_source_array(
const auto N = mesh.quadratures.gll.N;

const auto el_type = properties.h_element_types(lcoord.ispec);
const int ncomponents = source_array.extent(2);
const int ncomponents = source_array.extent(0);

// Compute lagrange interpolants at the source location
auto [hxi_source, hpxi_source] =
Expand Down
2 changes: 1 addition & 1 deletion src/source/moment_tensor_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void specfem::sources::moment_tensor::compute_source_array(
"Moment tensor source not implemented for acoustic medium");
}

const int ncomponents = source_array.extent(2);
const int ncomponents = source_array.extent(0);
if (ncomponents != 2) {
throw std::runtime_error(
"Moment tensor source requires 2 components for elastic medium");
Expand Down
6 changes: 6 additions & 0 deletions src/source/read_sources.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "source/external.hpp"
#include "source/force_source.hpp"
#include "source/interface.hpp"
#include "source/moment_tensor_source.hpp"
#include "specfem_setup.hpp"
Expand Down Expand Up @@ -39,6 +41,9 @@ specfem::sources::read_sources(
} else if (YAML::Node moment_tensor_source = N["moment-tensor"]) {
sources.push_back(std::make_shared<specfem::sources::moment_tensor>(
moment_tensor_source, nsteps, dt, source_wavefield_type));
} else if (YAML::Node external = N["user-defined"]) {
sources.push_back(std::make_shared<specfem::sources::external>(
external, nsteps, dt, source_wavefield_type));
} else if (YAML::Node adjoint_source = N["adjoint-source"]) {
sources.push_back(std::make_shared<specfem::sources::adjoint_source>(
adjoint_source, nsteps, dt));
Expand All @@ -59,6 +64,7 @@ specfem::sources::read_sources(
type_real t0 = std::numeric_limits<type_real>::max();
for (auto &source : sources) {
type_real cur_t0 = source->get_t0();
std::cout << cur_t0 << std::endl;
if (cur_t0 < t0) {
t0 = cur_t0;
}
Expand Down
19 changes: 14 additions & 5 deletions src/source_time_function/external.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ specfem::forcing_function::external::external(const YAML::Node &external,
const int nsteps,
const type_real dt)
: __nsteps(nsteps), __dt(dt),
__filename(external["filename"].as<std::string>()) {
__filename(external["stf-file"].as<std::string>()) {

if ((external["format"].as<std::string>() == "ascii") ||
(external["format"].as<std::string>() == "ASCII")) {
Expand All @@ -19,7 +19,9 @@ specfem::forcing_function::external::external(const YAML::Node &external,
throw std::runtime_error("Only ASCII format is supported");
}

std::vector<std::string> extentions = { "BXX.semd", "BXY.semd" };
std::vector<std::string> extentions = { ".BXX.semd", ".BXY.semd" };

int file_components = 0;

// get t0 from file
for (int icomp = 0; icomp < 2; ++icomp) {
Expand All @@ -35,10 +37,17 @@ specfem::forcing_function::external::external(const YAML::Node &external,
" is not formatted correctly");
}
this->__t0 = time;
file_components++;
}
file.close();
}

if (file_components != 1) {
throw std::runtime_error(
"Wrong number for files found for external source: " +
this->__filename);
}

return;
}

Expand All @@ -50,9 +59,9 @@ void specfem::forcing_function::external::compute_source_time_function(

const auto extention = [&ncomponents]() -> std::vector<std::string> {
if (ncomponents == 2) {
return { "BXX.semd", "BXZ.semd" };
return { ".BXX.semd", ".BXZ.semd" };
} else if (ncomponents == 1) {
return { "BXY.semd" };
return { ".BXY.semd" };
} else {
throw std::runtime_error("Invalid number of components");
}
Expand All @@ -69,7 +78,7 @@ void specfem::forcing_function::external::compute_source_time_function(
}

for (int icomp = 0; icomp < ncomponents; ++icomp) {
specfem::kokkos::HostView2d<type_real> data("external", nsteps);
specfem::kokkos::HostView2d<type_real> data("external", nsteps, 2);
specfem::reader::seismogram reader(
this->__filename + extention[icomp],
specfem::enums::seismogram::format::ascii, data);
Expand Down

0 comments on commit 90129c9

Please sign in to comment.