35 #include "navier_stokes.h"    36 #include "fluid_interface.h"    39 #include "meshes/bretherton_spine_mesh.h"    43 using namespace oomph;
    80  void inflow(
const Vector<double>& x, Vector<double>& veloc)
    83   std::ostringstream error_stream;
    84   bool throw_error=
false;
    87     error_stream << 
"You must set H_lo_pt\n";
    92     error_stream << 
"You must set H_up_pt\n";
    97     error_stream << 
"You must set Y_lo_pt\n";
   102     error_stream << 
"You must set Y_up_pt\n";
   109     throw OomphLibError(error_stream.str(),
   110                         OOMPH_CURRENT_FUNCTION,
   111                         OOMPH_EXCEPTION_LOCATION);
   117   double h_av=0.5*(*H_lo_pt+*
H_up_pt);
   124   double C =6.0*(2.0*h_av+y_lo-y_up)/
   125    (y_up*y_up*y_up-y_lo*y_lo*y_lo-h_av*y_up*
   126     y_up*y_up+h_av*y_lo*y_lo*y_lo-3.0*y_lo*y_up*y_up+
   127     3.0*y_lo*y_lo*y_up+3.0*y_lo*y_up*y_up*h_av-3.0*y_lo*y_lo*y_up*h_av);
   133   veloc[0]=-1.0+C*(1.0-h_av)*((y_lo-y)*(y_up-y));
   156 template<
class ELEMENT>
   164  typedef void (*InflowFctPt)(
const Vector<double>& x, Vector<double>& veloc);
   176   const Vector<Data*>& inflow_ext_data,
   177   const unsigned& inflow_boundary,
   178   InflowFctPt inflow_fct_pt)
   181    unsigned n_ext=inflow_ext_data.size();
   182    Inflow_ext_data.resize(n_ext);
   183    for (
unsigned i=0;i<n_ext;i++)
   185      Inflow_ext_data[i]=inflow_ext_data[i];
   188    Inflow_boundary=inflow_boundary;
   190    Inflow_fct_pt=inflow_fct_pt;
   199    ELEMENT::assign_local_eqn_numbers(store_local_dof_pt);
   205    unsigned local_eqn_count = this->ndof();
   209    unsigned max_nvalue=0;
   210    unsigned n_ext=Inflow_ext_data.size();
   211    for (
unsigned i=0;i<n_ext;i++)
   214      Data* data_pt=Inflow_ext_data[i];
   216      unsigned n_val=data_pt->nvalue();
   217      if (n_val>max_nvalue) max_nvalue=n_val;
   221    Inflow_ext_data_eqn.resize(n_ext,max_nvalue);
   224    std::deque<unsigned long> global_eqn_number_queue;
   227    for (
unsigned i=0;i<n_ext;i++)
   230      Data* data_pt=Inflow_ext_data[i];
   233      unsigned n_val=data_pt->nvalue();
   234      for (
unsigned ival=0;ival<n_val;ival++)
   238        long eqn_number=data_pt->eqn_number(ival);
   242          global_eqn_number_queue.push_back(eqn_number);
   244          Inflow_ext_data_eqn(i,ival)=local_eqn_count;
   250          Inflow_ext_data_eqn(i,ival)=-1;
   256    this->add_global_eqn_numbers(global_eqn_number_queue, 
   257                                 GeneralisedElement::Dof_pt_deque);
   266                    DenseMatrix<double>& jacobian)
   269    unsigned n_ext=Inflow_ext_data.size();
   272    ELEMENT::get_jacobian(residuals,jacobian);
   274    if (n_ext==0) 
return;
   277    Vector<double> residuals_plus(residuals.size());
   278    double fd_step=1.0e-8;
   281    for (
unsigned i=0;i<n_ext;i++)
   284      Data* data_pt=Inflow_ext_data[i];
   287      unsigned n_val=data_pt->nvalue();
   288      for (
unsigned ival=0;ival<n_val;ival++)
   291        int local_eqn=Inflow_ext_data_eqn(i,ival);
   297          double *value_pt = data_pt->value_pt(ival);
   300          double backup = *value_pt;
   303          *value_pt += fd_step;
   310          unsigned n_dof = this->ndof();
   312          for(
unsigned idof=0;idof<n_dof;idof++) {residuals_plus[idof] = 0.0;}
   314          this->get_residuals(residuals_plus);
   316          for(
unsigned idof=0;idof<n_dof;idof++)
   318            jacobian(idof,local_eqn)=
   319             (residuals_plus[idof]-residuals[idof])/fd_step;
   348    Vector<double> veloc(2);
   349    unsigned n_nod = this->nnode();
   350    for (
unsigned j=0;j<n_nod;j++)
   352      Node* nod_pt = this->node_pt(j);
   354      if(nod_pt->is_on_boundary(Inflow_boundary))
   357            for (
unsigned i=0;i<2;i++)
   359              if (nod_pt->eqn_number(0)>=0)
   361                std::ostringstream error_stream;
   363                 << 
"We're assigning a Dirichlet condition for the "    365                 << 
"velocity, even though it is not pinned!\n"    366                 << 
"This can't be right! I'm bailing out..."    369                throw OomphLibError(error_stream.str(),
   370                                    OOMPH_CURRENT_FUNCTION,
   371                                    OOMPH_EXCEPTION_LOCATION);
   378            Inflow_fct_pt(x,veloc);
   379            nod_pt->set_value(0,veloc[0]);
   380            nod_pt->set_value(1,veloc[1]);
   412 class FaceGeometry<
BrethertonElement<SpineElement<QCrouzeixRaviartElement<2> > > >: 
public virtual QElement<1,3>
   424 class FaceGeometry<
BrethertonElement<SpineElement<QTaylorHoodElement<2> > > >: 
public virtual QElement<1,3>
   437  SpineElement<QCrouzeixRaviartElement<2> > > > >: 
public virtual PointElement
   450 class FaceGeometry<FaceGeometry<
BrethertonElement<SpineElement<QTaylorHoodElement<2> > > > >: 
public virtual PointElement
   467 template<
class ELEMENT>
   484    Bulk_mesh_pt->node_update();
   488    unsigned num_nod=mesh_pt()->nboundary_node(ibound);
   492    Vector<double> veloc(2);
   495    for (
unsigned inod=0;inod<num_nod;inod++)
   498      x[0]=mesh_pt()->boundary_node_pt(ibound,inod)->x(0);
   499      x[1]=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
   503      mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,veloc[0]);
   504      mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1,veloc[1]);
   517                    const double &pvalue)
   520    dynamic_cast<ELEMENT *
>(Bulk_mesh_pt->element_pt(e))->
   521     fix_pressure(l,pvalue);
   527  void activate_inflow_dependency();
   530  void parameter_study(
const unsigned& nsteps); 
   533  void doc_solution(DocInfo& doc_info);
   545  BrethertonSpineMesh<ELEMENT,SpineLineFluidInterfaceElement<ELEMENT> >* 
   554 template<
class ELEMENT>
   579  GeomObject* lower_wall_pt=
new StraightLine(-1.0);
   580  GeomObject* upper_wall_pt=
new StraightLine( 1.0);
   592  Bulk_mesh_pt = 
new  BrethertonSpineMesh<ELEMENT,
   593   SpineLineFluidInterfaceElement<ELEMENT> > 
   594   (nx1,nx2,nx3,nh,nhalf,h,lower_wall_pt,upper_wall_pt,xi0,0.0,xi1,xi2);
   597  mesh_pt()=Bulk_mesh_pt;
   600  Control_element_pt=Bulk_mesh_pt->control_element_pt();
   607   Bulk_mesh_pt->spine_pt(0)->spine_height_pt()->value_pt(0);
   610  unsigned last_spine=Bulk_mesh_pt->nfree_surface_spines()-1;
   612   Bulk_mesh_pt->spine_pt(last_spine)->spine_height_pt()->value_pt(0);
   617   Bulk_mesh_pt->boundary_node_pt(ibound,0)->x_pt(0,1);
   620  unsigned nnod=Bulk_mesh_pt->nboundary_node(ibound);
   622   Bulk_mesh_pt->boundary_node_pt(ibound,nnod-1)->x_pt(0,1);
   625  activate_inflow_dependency();
   632  for(
unsigned ibound=0;ibound<=2;ibound++)
   634    unsigned num_nod=mesh_pt()->nboundary_node(ibound);
   635    for (
unsigned inod=0;inod<num_nod;inod++)
   637      mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
   638      mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
   643  for(
unsigned ibound=3;ibound<=5;ibound+=2)
   645    unsigned num_nod=mesh_pt()->nboundary_node(ibound);
   646    for (
unsigned inod=0;inod<num_nod;inod++)
   648      mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
   649      mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
   654  unsigned central_spine=(Bulk_mesh_pt->nfree_surface_spines()-1)/2;
   655  Bulk_mesh_pt->spine_pt(central_spine)->spine_height_pt()->pin(0);
   659  for (
unsigned ibound=0;ibound<=2;ibound+=2)
   661    unsigned num_nod=mesh_pt()->nboundary_node(ibound);
   662    for (
unsigned inod=0;inod<num_nod;inod++)
   665      mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,-1.0);
   666      mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1, 0.0);
   672  for (
unsigned ibound=3;ibound<=5;ibound+=2)
   674    unsigned num_nod=mesh_pt()->nboundary_node(ibound);
   675    for (
unsigned inod=0;inod<num_nod;inod++)
   678      mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,-1.0);
   679      mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1, 0.0);
   688  unsigned n_bulk=Bulk_mesh_pt->nbulk();
   689  for(
unsigned i=0;i<n_bulk;i++)
   692    ELEMENT *el_pt = 
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->
   702  unsigned interface_element_pt_range = Bulk_mesh_pt->ninterface_element();
   703  for(
unsigned i=0;i<interface_element_pt_range;i++)
   706    SpineLineFluidInterfaceElement<ELEMENT>* el_pt = 
   707     dynamic_cast<SpineLineFluidInterfaceElement<ELEMENT>*
>   708     (Bulk_mesh_pt->interface_element_pt(i));
   716  Bulk_mesh_pt->node_update();
   719  cout << 
"Number of unknowns: " << assign_eqn_numbers() << std::endl; 
   729 template<
class ELEMENT>
   734  Vector<Data*> outflow_spines(2);
   737  outflow_spines[0]=Bulk_mesh_pt->spine_pt(0)->spine_height_pt();
   740  unsigned last_spine=Bulk_mesh_pt->nfree_surface_spines()-1;
   741  outflow_spines[1]=Bulk_mesh_pt->spine_pt(last_spine)->spine_height_pt();;
   747  unsigned nel=Bulk_mesh_pt->nboundary_element(ibound);
   748  for (
unsigned e=0;e<nel;e++)
   751    ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->
   752                                          boundary_element_pt(ibound,e));  
   754    el_pt->activate_inflow_dependency_on_external_data(
   765 template<
class ELEMENT>
   781  unsigned last_spine=Bulk_mesh_pt->nfree_surface_spines()-1;
   785  Trace_file << 
" " << Bulk_mesh_pt->spine_pt(0)->height();
   786  Trace_file << 
" " << Bulk_mesh_pt->spine_pt(last_spine)->height();
   787  Trace_file << 
" " << 1.3375*pow(Global_Physical_Variables::Ca,2.0/3.0);
   788  Trace_file << 
" " << -Control_element_pt->interpolated_p_nst(s)*
   790  Trace_file << 
" " << 1.0+3.8*pow(Global_Physical_Variables::Ca,2.0/3.0);
   791  Trace_file << 
" " << Control_element_pt->interpolated_u_nst(s,0);
   792  Trace_file << 
" " << Control_element_pt->interpolated_u_nst(s,1);
   793  Trace_file << std::endl;
   797  sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
   799  some_file.open(filename);
   800  Bulk_mesh_pt->output(some_file,npts);
   805  sprintf(filename,
"%s/boundaries%i.dat",doc_info.directory().c_str(),
   807  some_file.open(filename);
   808  Bulk_mesh_pt->output_boundaries(some_file);
   819 template<
class ELEMENT>
   824  Problem::Max_residuals=100.0;
   828  doc_info.set_directory(
"RESLT");
   834  sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
   835  Trace_file.open(filename);
   837  Trace_file << 
"VARIABLES=\"Ca\",";
   838  Trace_file << 
"\"h<sub>bottom</sub>\",\"h<sub>too</sub>\",";
   839  Trace_file << 
"\"h<sub>Bretherton</sub>\",\"p<sub>tip</sub>\",";
   840  Trace_file << 
"\"p<sub>tip (Bretherton)</sub>\",\"u<sub>stag</sub>\",";
   841  Trace_file << 
"\"v<sub>stag</sub>\"";
   842  Trace_file << 
"\"<greek>a</greek><sub>bottom</sub>\",";
   843  Trace_file << 
"\"<greek>a</greek><sub>top</sub>\"";
   844  Trace_file << std::endl;
   850  doc_solution(doc_info);
   853  for (
unsigned step=1;step<=nsteps;step++)
   855    cout << std::endl << 
"STEP " << step << std::endl;
   864      cout << 
"Checking max. res for Ca = "    868      DoubleVector residuals;
   869      actions_before_newton_solve();
   870      actions_before_newton_convergence_check();
   871      get_residuals(residuals);
   872      double max_res=residuals.max();
   878        cout << 
". Too big!" << std::endl;
   880        Global_Physical_Variables::Ca *= factor;       
   882        factor=1.0+(factor-1.0)/1.5;
   883        cout << 
"New reduction factor: " << factor << std::endl;
   885        Global_Physical_Variables::Ca /= factor;
   892        cout << 
". OK" << std::endl << std::endl;
   899    cout << 
"Solving for capillary number: "    905    doc_solution(doc_info);
   920 int main(
int argc, 
char* argv[]) 
   925  CommandLineArgs::setup(argc,argv);
   951  if (CommandLineArgs::Argc>1)
 double * Y_up_pt
Pointer to y-position at inflow on the upper wall. 
 
BrethertonElement()
Constructor: Call the constructor of the underlying element. 
 
Vector< Data * > Inflow_ext_data
Storage for the external Data that affects the inflow. 
 
BrethertonProblem()
Constructor: 
 
void actions_before_newton_convergence_check()
Spine heights/lengths are unknowns in the problem so their values get corrected during each Newton st...
 
double * H_up_pt
Pointer to film thickness at outflow on the upper wall. 
 
Vector< double > G(2)
Direction of gravity. 
 
void fix_pressure(const unsigned &e, const unsigned &l, const double &pvalue)
Fix pressure value l in element e to value p_value. 
 
void activate_inflow_dependency()
Activate the dependency of the inflow velocity on the spine heights at the outflow. 
 
void activate_inflow_dependency_on_external_data(const Vector< Data *> &inflow_ext_data, const unsigned &inflow_boundary, InflowFctPt inflow_fct_pt)
Activate the dependency of the "inflow" on the external data. Pass the vector of pointers to the exte...
 
double ReSt
Womersley = Reynolds times Strouhal. 
 
unsigned Inflow_boundary
Number of the inflow boundary in the global mesh. 
 
void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
 
void reassign_inflow()
For all nodes that are located on specified boundary re-assign the inflow velocity, using the function pointed to by the function pointer. 
 
int main(int argc, char *argv[])
 
void inflow(const Vector< double > &x, Vector< double > &veloc)
 
double Re
Reynolds number. 
 
void actions_before_newton_solve()
Update before solve: empty. 
 
double * Y_lo_pt
Pointer to y-position at inflow on the lower wall. 
 
Namepspace for global parameters. 
 
void actions_after_newton_solve()
Update after solve can remain empty, because the update is performed automatically after every Newton...
 
double ReInvFr
Product of Reynolds and Froude number. 
 
ELEMENT * Control_element_pt
Pointer to control element. 
 
ofstream Trace_file
Trace file. 
 
void assign_local_eqn_numbers(const bool &store_local_dof_pt)
 
void doc_solution(DocInfo &doc_info)
Doc the solution. 
 
DenseMatrix< int > Inflow_ext_data_eqn
Storage for the local equation numbers associated the Data values that affect the inflow...
 
BrethertonSpineMesh< ELEMENT, SpineLineFluidInterfaceElement< ELEMENT > > * Bulk_mesh_pt
Pointer to bulk mesh. 
 
void parameter_study(const unsigned &nsteps)
Run a parameter study; perform specified number of steps. 
 
InflowFctPt Inflow_fct_pt
Function pointer to the global function that specifies the inflow velocity profile on the global mesh...
 
double Ca
Capillary number. 
 
double * H_lo_pt
Pointer to film thickness at outflow on the lower wall.