static WEPolyhedron *compute_polyhedron(
    Triangulation   *manifold)
{
    int             i;
    WEPolyhedron    *polyhedron;

    static const int    num_precisions = 5;
    static const Real precision[5] = {1e-8, 1e-6, 1e-10, 1e-4, 1e-12};

    for (i = 0; i < num_precisions; i++)
    {
        polyhedron = Dirichlet( manifold,
                                precision[i], 
                                TRUE,
                                Dirichlet_stop_here,
                                TRUE);
        if (polyhedron != NULL)
            return polyhedron;
    }

    /*
     *  Even after trying five precisions we still couldn't
     *  get a Dirichlet domain.
     */
    return NULL;
}
void 
UZRectMollerup::upperboundary (const GeometryRect& geo,
                               const Soil& soil,
                               const ublas::vector<double>& T,
			       const Surface& surface,
                               std::vector<top_state>& state,
			       const ublas::vector<double>& remaining_water,
			       const ublas::vector<double>& h,
			       const ublas::vector<double>& Kedge,
			       ublas::vector<double>& dq,
			       ublas::banded_matrix<double>& Dm_mat, 
			       ublas::vector<double>& Dm_vec, 
			       ublas::vector<double>& Gm, 
			       ublas::vector<double>& B,
			       const double ddt,
			       const int debug,
                               Treelog& msg, const double BIG_DT)
{
  const std::vector<size_t>& edge_above = geo.cell_edges (Geometry::cell_above);
  const size_t edge_above_size = edge_above.size ();

  for (size_t i = 0; i < edge_above_size; i++)
    {
      const size_t edge = edge_above[i];
      const int cell = geo.edge_other (edge, Geometry::cell_above);
      daisy_assert (geo.cell_is_internal (cell));
      const double in_sign 
        = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
      daisy_assert (in_sign < 0);
      const double area = geo.edge_area (edge);
      const double sin_angle = geo.edge_sin_angle (edge);

      switch (surface.top_type (geo, edge))
	{
	case Surface::forced_flux: 
          {
            const double flux = -surface.q_top (geo, edge, BIG_DT);
            Neumann (edge, cell, area, in_sign, flux, dq, B);
          }
	  break;
	case Surface::forced_pressure:
          {
            const double value = -Kedge (edge) * geo.edge_area_per_length (edge);
            const double pressure = surface.h_top (geo, edge);
            Dirichlet (edge, cell, area, in_sign, sin_angle, 
                       Kedge (edge), 
                       h (cell), value, pressure, dq, Dm_mat, Dm_vec, Gm);
          }
	  break;
	case Surface::limited_water:
          {
            const double h_top = remaining_water (i);

            // We pretend that the surface is particlaly saturated.
            const double K_sat = soil.K (cell, 0.0, 0.0, T (cell));
            const double K_cell = Kedge (edge);
            const double K_edge = 0.5 * (K_cell + K_sat);
            
            const double dz = geo.edge_length (edge);
            daisy_assert (approximate (dz, -geo.cell_z (cell)));
            double q_in_avail = h_top / ddt;
            const double q_in_pot = K_edge * (h_top - h (cell) + dz) / dz;
            // Decide type.
            bool is_flux = h_top <= 0.0 || q_in_pot > q_in_avail;

            if (is_flux)
              {
                state[i] = top_flux;
                Neumann (edge, cell, area, in_sign, q_in_avail, dq, B);
              }
            else			// Pressure
              {
                state[i] = top_pressure;
                if (debug > 0 && q_in_pot < 0.0)
                  {
                    std::ostringstream tmp;
                    tmp << "q_in_pot = " << q_in_pot << ", q_avail = " 
                        << q_in_avail << ", h_top = " << h_top 
                        << ", h (cell) = " << h (cell) 
                        << " K (edge) = " << Kedge (edge) 
                        << ", K_sat = " << K_sat << ", K_edge = "
                        << K_edge <<", dz = " << dz << ", ddt = " << ddt
                        << ", is_flux = " << is_flux << "\n";
                    msg.message (tmp.str ());
                  }
                const double value = -K_edge * geo.edge_area_per_length (edge);
                const double pressure = h_top;
                Dirichlet (edge, cell, area, in_sign, sin_angle, 
                           K_edge, h (cell),
                           value, pressure, dq, Dm_mat, Dm_vec, Gm);
              }
            if (debug == 3)
              {
                std::ostringstream tmp;
                tmp << "edge = " << edge << ", K_edge = " << K_edge 
                    << ", h_top = "
                    << h_top << ", dz = " << dz << ", q_avail = " << q_in_avail
                    << ", q_pot = " << q_in_pot << ", is_flux = " << is_flux;
                msg.message (tmp.str ());
              }
          }
	  break;
	case Surface::soil:
	  throw "Don't know how to handle this surface type";
	default:
	  daisy_panic ("Unknown surface type");
	}
    }
}
void 
UZRectMollerup::lowerboundary (const GeometryRect& geo,
			       const Groundwater& groundwater,
			       const std::vector<bool>& active_lysimeter,
			       const ublas::vector<double>& h,
			       const ublas::vector<double>& Kedge,
			       ublas::vector<double>& dq,
			       ublas::banded_matrix<double>& Dm_mat, 
			       ublas::vector<double>& Dm_vec, 
			       ublas::vector<double>& Gm, 
			       ublas::vector<double>& B, Treelog& msg)
{
  const std::vector<size_t>& edge_below = geo.cell_edges (Geometry::cell_below);
  const size_t edge_below_size = edge_below.size ();

  for (size_t i = 0; i < edge_below_size; i++)
    {
      const size_t edge = edge_below[i];
      const int cell = geo.edge_other (edge, Geometry::cell_below);
      daisy_assert (geo.cell_is_internal (cell));
      const double in_sign 
        = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
      daisy_assert (in_sign > 0);
      const double area = geo.edge_area (edge);
      const double sin_angle = geo.edge_sin_angle (edge);

      switch (groundwater.bottom_type ())
        {
        case Groundwater::free_drainage:
          {
            const double sin_angle = geo.edge_sin_angle (edge);
            //const double flux = -in_sign * sin_angle * K (cell) * area; //old
            const double flux = -in_sign * sin_angle * Kedge (edge);
            Neumann (edge, cell, area, in_sign, flux, dq, B);
          }
          break;
          
        case Groundwater::forced_flux:
          {
            const double flux = groundwater.q_bottom (edge);
            Neumann (edge, cell, area, in_sign, flux, dq, B);
          }
          break;
        
        case Groundwater::pressure:
          {
            const double value = -Kedge (edge) * geo.edge_area_per_length (edge);
            const double pressure =  groundwater.table () - geo.zplus (cell);
            
            Dirichlet (edge, cell, area, in_sign, sin_angle, 
                       Kedge (edge), 
                       h (cell),
                       value, pressure,
                       dq, Dm_mat, Dm_vec, Gm);
          }
          break;

        case Groundwater::lysimeter:
          {
            if (active_lysimeter[cell])
              {
                //Neumann - not so good
                //const double flux = -in_sign * sin_angle * K (cell);
                //Neumann (edge, cell, area, in_sign, flux, dq, B);
                //Dirichlet - better
                const double value = -Kedge (edge) * geo.edge_area_per_length (edge);
                const double pressure =  0.0;
                Dirichlet (edge, cell, area, in_sign, sin_angle,
                           Kedge (edge), 
                           h (cell),
                           value, pressure, dq, Dm_mat, Dm_vec, Gm);
              }
            else
              // Indsat af [email protected] Fri Jul 10 11:21:14     2009
              {
                const double flux = 0.0;
                Neumann (edge, cell, area, in_sign, flux, dq, B);
              }

          }
          break;
          
        default:
          daisy_panic ("Unknown groundwater type");
        }
    }
}
Example #4
0
void makeFlux(FVMesh2D &m, FVVect<double> &phi, FVVect< FVPoint2D<double> > &u,
              FVVect<double> &Vd,FVVect<double> &Vn,
              FVVect<double> &F,Parameter &para) {

    //FVEdge2D *ptr_e;
    double leftPhi,rightPhi,normal_velocity;
    FVPoint2D<double> BB;
    m.beginEdge();
    size_t edges = m.getNbEdge();

    //avoid getting static values in loops
    const unsigned int dirCode = para.getUnsigned("DirichletCode");
    const unsigned int neuCode = para.getUnsigned("NeumannCode");
    const double difusion = getDiffusion(NULL,para);        
    
    
    #pragma omp parallel for private(normal_velocity,leftPhi,rightPhi)
    for(size_t i = 0; i < edges; i++) {

        FVEdge2D *ptr_e;
        //ptr_e = m.nextEdge();
        ptr_e = m.getEdge(i);
        
        normal_velocity = Dot(u[ptr_e->label-1],ptr_e->normal);  
        leftPhi = phi[ptr_e->leftCell->label-1];
        
        if(ptr_e->rightCell) {
            // edge has the code = 0    
            
            rightPhi = phi[ptr_e->rightCell->label-1];
            // compute the convection contribution
            if(normal_velocity<0) {
              
                F[ptr_e->label-1] = normal_velocity*rightPhi;
            }
            else {
              
                F[ptr_e->label-1] = normal_velocity*leftPhi;   
            }
            // compute the diffusive contribution
            BB=ptr_e->rightCell->centroid - ptr_e->leftCell->centroid;                        
            
            F[ptr_e->label-1] -= difusion*(rightPhi-leftPhi)/Norm(BB); 

         }
          else {
            //  we are on the boundary
            if(ptr_e->code == dirCode) {                
                // we have a Dirichlet condition                
                rightPhi = Dirichlet(ptr_e->centroid,para);
                // compute the convection contribution
                if(normal_velocity<0) {
                    
                    F[ptr_e->label-1] = normal_velocity*rightPhi;
                }
                else {
                    
                    F[ptr_e->label-1] = normal_velocity*leftPhi;   
                }
                // compute the diffusive contribution                
                BB = ptr_e->centroid - ptr_e->leftCell->centroid;
               
                F[ptr_e->label-1] -= difusion*(rightPhi-leftPhi)/Norm(BB); 
            }
             
            if(ptr_e->code == neuCode) {
                // we have a Neumann condition      
                
                F[ptr_e->label-1] = Neumann(ptr_e->centroid,para);
            }
        }

        // here, we have all the data to compute the flux    
        
        F[ptr_e->label-1] *= ptr_e->length;
    }
}
Example #5
0
void viterbi(int *x_T, int *x_N, double *x_A, double *x_Pi, double *mu, double *sigma,
			 double *obs, int *overlap, double *overlaps, int *overlap_ids, int *no_overlaps,
			 int *start_overlaps, int *dist, int *L, int *distance, double *P, int *Q,
			 double *mean_ref, double *sd_min, double *mean_sd, int *prior,
			 double *x_W_A, double *W_Pi) {
		
		int N = *x_N;
		int T = *x_T;
		double A[N][N];
		double W_A[N][N];
		double Pi[N];
		
		double delta[T][N];
		int psi[T][N];
		
		// Fill A and Pi
		for (int i = 0; i < N; i++) {
				for (int j = 0, index = i; j < N; j++, index += N) {
						if (*dist)
								A[i][j] = x_A[index];
						else
								A[i][j] = safe_log(x_A[index]);
						W_A[i][j] = x_W_A[index];
				}
				Pi[i] = safe_log(x_Pi[i]);
		}
				
		// Initialization
		for (int i = 0; i < N; i++) {
				delta[0][i] = emission_prob(obs[0], mu[i], sigma[i], 1) + Pi[i];
		}
		
		// Recursion
		int no_olaps;
		int start;
		double sum_olap;
		double trans;
		if (T > 1) {
				for (int t = 1; t < T; t++) {
						
						no_olaps = no_overlaps[t];
						int olap_ids[no_olaps];
						double olaps[no_olaps];
						start = start_overlaps[t];
						sum_olap = 1.0;
						
						if (*overlap) {
								for (int i = 0; i < no_olaps; i++) {
										olap_ids[i] = overlap_ids[start + i];
										olaps[i] = overlaps[start + i];
										sum_olap += olaps[i];
								}
								olaps[no_olaps-1] = 1.0;
						}
						
						for (int j = 0; j < N; j++) {
								double prev[N];
								if (*dist)
										prev[0] = safe_log(trans_dist(distance[t], A[0][j],
																	  *L, N)) +
												delta[t-1][0];
								else
										prev[0] = A[0][j] + delta[t-1][0];
								double max = prev[0];
								int maxid = 0;
								if (N > 1) {
										for (int i = 1; i < N; i++) {
												if (*dist)
														prev[i] = safe_log(trans_dist(distance[t],
																					  A[i][j],
																					  *L, N)) +
																delta[t-1][i];
												else
														prev[i] = A[i][j] + delta[t-1][i];
												if (prev[i] > max) {
														maxid = i;
														max = prev[i];
												}
										}
								}
								
								psi[t][j] = maxid;

								trans = 0.0;
								
								if (*overlap) {
										int qt[no_olaps];
										if (no_olaps > 1) {
												int q = j;
												int iter = no_olaps-2;
												for (int i = t-1; i >= olap_ids[0]; i--) {
														q = psi[i+1][q];
														if (member(i, olap_ids, no_olaps)) {
																qt[iter] = q;
																iter--;
														}
												}
										}
										qt[no_olaps-1] = j;
										
										int id;
										for (int i = 0; i < no_olaps; i++) {
												id = qt[i];
												trans += emission_prob(obs[t], mu[id], sigma[id], 1) +
														safe_log(olaps[i] / sum_olap);
										}
								}
								else {
										trans = emission_prob(obs[t], mu[j], sigma[j], 1);
								}

								if (*dist)
										delta[t][j] = delta[t-1][psi[t][j]] +
												safe_log(trans_dist(distance[t], A[psi[t][j]][j], *L, N)) +
												trans;
								else
										delta[t][j] = delta[t-1][psi[t][j]] + A[psi[t][j]][j] + trans;
						}
				}
		}
		
		// Termination
		double max = delta[T-1][0];
		int maxid = 0;
		if (N > 1) {
				for (int i = 1; i < N; i++) {
						if (delta[T-1][i] > max) {
								maxid = i;
								max = delta[T-1][i];
						}
				}
		}
		Q[T-1] = maxid;
		*P = delta[T-1][Q[T-1]];

		// Calculate parameter prior probability
		if (*prior) {
				for (int i = 0; i < N; i++) {
						*P += safe_log(Dirichlet(A[i], W_A[i], N));
						*P += safe_log(*sd_min / sigma[i]) +
								emission_prob(mu[i], mean_ref[i], *mean_sd, 1);
				}
				*P += safe_log(Dirichlet(Pi, W_Pi, N));
		}
		
		// Path backtracking
		if (T > 1) {
				for (int t = T-2; t >= 0; t--) {
						Q[t] = psi[t+1][Q[t+1]];
				}
		}
}