Hello,
I want to propagate a wave in a square mesh going from left to right.
What I got so far is the left boundary changing according the the sinusoidal law I imposed, but the solution is not propagating. Clearly I must be doing something wrong in the time-stepping, like I'm probably not saving the current solution to be reused as initial condition.
I have no idea how to do so. Any help is appreciated.
#include <dolfin.h>
#include "Wave.h"
#include <mshr.h>
using namespace dolfin;
// Source term for boundary condition
class Source_BC : public Expression
{
public:
// Constructor
Source_BC() : t(0) {}
// Evaluate wave at left boundary
void eval(Array<double>& values, const Array<double>& x) const
{
double eps = 1e-1;
values[0] = -std::cos(eps*t);
}
// Current time
double t;
};
// Sub domain for Dirichlet boundary condition
class DirichletBCLeft : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
return x[0] < -1.0 + DOLFIN_EPS;
}
};
class DirichletBCUp : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
return x[1] > 1.0 - DOLFIN_EPS ;
}
};
class DirichletBCRight : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
return x[0] > 1.0 - DOLFIN_EPS;
}
};
class DirichletBCDown : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
return x[1] < -1.0 + DOLFIN_EPS;
}
};
int main()
{
// Parameters for the Newmark beta method
double beta = 0.25;
double gamma = 0.5;
auto dt = std::make_shared<Constant>(1);
double T = 10*(*dt);
// Mesh definition
auto rectangle = mshr::Rectangle(dolfin::Point(-1.0, 1.0, 0.0), dolfin::Point(1.0, -1.0, 0.0));
auto mesh = mshr::generate_mesh(rectangle, 50);
auto V = std::make_shared<Wave::FunctionSpace>(mesh);
auto b1 = std::make_shared<Source_BC>();
auto boundary1 = std::make_shared<DirichletBCLeft>();
auto boundary2 = std::make_shared<DirichletBCUp>();
auto boundary3 = std::make_shared<DirichletBCRight>();
auto boundary4 = std::make_shared<DirichletBCDown>();
DirichletBC bc1(V, b1, boundary1);
DirichletBC bc2(V, std::make_shared<Constant>(0.0), boundary2);
DirichletBC bc3(V, std::make_shared<Constant>(0.0), boundary3);
DirichletBC bc4(V, std::make_shared<Constant>(0.0), boundary4);
std::vector<const DirichletBC*> bcs = {&bc1, &bc2, &bc3, &bc4};
Function u(V);
Function u0(V);
auto f = std::make_shared<Constant>(0.0);
// Create forms
Wave::BilinearForm a(V, V);
Wave::LinearForm L(V);
L.f = f;
//solve(a == L, u, bcs);
File file("Wave.pvd");
double t;
while (t < T + DOLFIN_EPS)
{
b1->t = t;
solve(a == L, u, bcs);
*u0.vector() = *u.vector();
t += *dt;
file << u;
}
// Plot solution
plot(u0);
interactive();
return 0;
}
# Compile this form with FFC: ffc -l dolfin Wave.ufl.
element = FiniteElement("Lagrange", triangle, 1)
u = TrialFunction(element)
v = TestFunction(element)
f = Coefficient(element)
a = u*v*dx
L = f*v*dx
Animaton of the results so far: